En mi experiencia, deberías tener un proceso ( único proceso que asigne folios a tus documentos ).

muchos procesos pueden insertar datos, pero solo un proceso debiera ser el encargado de asignar esos folios. ( cuando era DBA para el registro civil de Chile ) fue la única forma de garantizar que los bloqueos se mantuvieran al mínimo.

Puedo estar equivocado, pero bajo mucho trafico la aplicación no se bloquea y los números de documentos son correlativos.

Es posible para tu aplicación usar esa lógica ?

On 9/8/2015 2:48 PM, mauricio pullabuestan wrote:
Buen día.

Tengo una función que devuelve el próximo número secuencial para mis
documentos, los cuales no pueden tener gaps ni overlaps

CREATE OR REPLACE FUNCTION prbsecuencia.movimiento_id(v_movimiento_id
integer)
   RETURNS integer AS
$BODY$
Declare v_key_new integer;
Begin
Update prbsecuencia.secuencia
  Set secuencia = secuencia + 1
  Where movimiento_id = v_movimiento_id
RETURNING secuencia INTO v_key_new;
  IF NOT FOUND THEN
     Insert Into prbsecuencia.secuencia Values (v_movimiento_id, 1)
RETURNING 1 INTO v_key_new;
END IF;
Return v_key_new;
end; $BODY$
   LANGUAGE plpgsql VOLATILE
   COST 100;
ALTER FUNCTION prbsecuencia.movimiento_id(integer)
   OWNER TO postgres;
Entonces desde mi aplicación hago:
Begin transaction
    Select nuevo_id From prbsecuencia.movimiento_id(10) t (nuevo_i)
   insert a la tabla cabecera, detalle y una par de tablas más.
Commit
Si falla la transacción hago un
Rollback.
Mis conocimientos en postgresql son básicos, tengo entendido que el
nivel de aislamiento por default en Postgresql es Read Committed, según
el nivel de aislamiento y la función no debería tener problemas, para
probar hice una pequeña aplicación con un
for de 1 a 20000
1.- Comienza una transacción
2.- Recupera el próximo secuencial
3.- Inserta datos a un par de tablas
4.- termina la transacción
Next
Instancie 4  veces la aplicación y corrí la aplicación todo iba bien
hasta más o menos 9000 interacciones de cada instancia entonces se
produjo un bloqueo en la cuarta instancia, tuve que matar la instancia y
las otras 3 instancias pudieron acabar el proceso, todo resulto como
esperaba, todas la instancias obtuvieron el número correspondiente no
hubo Gaps y overlaps.
La duda porque se dio el bloqueo?
Con postgresql basta con el nivel de aislamiento por default para
garantizar la distribución correcta o se puede reforzar, como con Sql
Server utilizo hints.
Como podría hacer para que desde una función llamar a la función
  prbsecuencia.movimiento_id() con 2 parametros,  el id de movimiento y
una variable, dentro de la función se le asigne el próximo número de
secuencia a la variable para luego usar la variable ya con el valor
correspondiente algo así:
CREATE OR REPLACE FUNCTION prbsecuencia.movimiento(parametro1 integer,
parametro2 integer)
   RETURNS Boolean AS
$BODY$
Declare key_new integer;
Begin
Select * From prbsecuencia.movimiento_id(10, key_new);
Insert Into cabecera (campo1, campo2, campo3) Values(key_new, ‘valor1’,
valor2);
Insert Into detalle (camp1, campo2, campo3) Values(key_new, ‘a’, ‘b’)
Return true;
end;
$BODY$
   LANGUAGE plpgsql VOLATILE
   COST 100;
Por lo que entiendo con el default Read Committed esto en un ambiente
multiusuario y con una alta concurrencia no debería tener problemas, si
los tuvieran cual es la manera correcta de hacerlo.
Saludos,
Mauricio

-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda@postgresql.org)
Para cambiar tu suscripci�n:
http://www.postgresql.org/mailpref/pgsql-es-ayuda

Responder a