Buen día.

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


CREATE OR REPLACEFUNCTION prbsecuencia.movimiento_id(v_movimiento_id integer)

  RETURNS integer AS

$BODY$

Declare v_key_newinteger;

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 elnivel de 
aislamiento por default en Postgresql es Read Committed, según elnivel de 
aislamiento y la función no debería tener problemas, para probar hiceuna 
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óny corrí la aplicación todo iba bien hasta más o 
menos 9000 interacciones decada instancia entonces se produjo un bloqueo en la 
cuarta instancia, tuve quematar la instancia y las otras 3 instancias pudieron 
acabar el proceso, todoresulto como esperaba, todas la instancias obtuvieron el 
número correspondienteno hubo Gaps y overlaps.


 
La duda porque se dio el bloqueo?


 
Con postgresql basta con el nivel de aislamiento por default para garantizar 
ladistribució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 
variablepara luego usar la variable ya con el valor correspondiente algo así:


 
CREATE OR REPLACE FUNCTION prbsecuencia.movimiento(parametro1 integer, 
parametro2integer)

  RETURNS Boolean AS

$BODY$

Declare key_newinteger;

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 
multiusuarioy con una alta concurrencia no debería tener problemas, si los 
tuvieran cual esla manera correcta de hacerlo.


 

 
Saludos,

Mauricio 

Responder a