El 27/07/2015 a las 17:10, Alvaro Herrera escribió:
Kernel escribió:

Por lo que veo hay varios casos en los que podemos obtener un deadlock de
estos :

1.- que una transacción t1 necesite que termine la t2 y esta t2 a su vez
necesita que termine t1 para poder terminar, entonces el gestor detecta esto
y elimina la mas antigua (por ejemplo la t1) y devuelve el deadlock en la
t1, y la t2 termina correctamente.

Esto es correcto, excepto que la transacción terminada no es
necesariamente la más antigua, sino la que primero detecta el deadlock.

Si en tu descripción de arriba reemplazas t1+t2 por un conjunto de
varias transacciones las cuales forman un ciclo de relaciones "ti
espera a tj", entonces lo de arriba es una descripción del algoritmo
general.

2.-   Empieza la transaccion t1(1) (varios insert en la tabla x), y despues
otro usuario lanza la misma transaccion t1(2), si la t1(1) tarda mucho
tiempo en terminar, el gestor devuelve el deadlock a la t1(1) y asi la t1(2)
se puede comenzar y terminar correctamente

Esta parte no es muy precisa.  Una inserción no causa que otras
transacciones se queden esperando.  En versiones antiguas podía suceder
si es que había llaves foráneas en las tablas involucradas, pero esto es
algo que hemos ido solucionando paulatinamente, y a menos que involucres
UPDATEs, no deberían ocurrir bloqueos ni deadlocks.


Tengo un proceso de cierre de inventario que puede tardar 10 minutos en
terminar  y no quiero que nadie pueda tocar la tabla , ni insertar,  ni
modificar.

No tengo clara esta parte.  Quizás quieras usar el modo SERIALIZABLE
(transaction isolation).

Había pensado que si pongo  'LOCK TABLE movimientos IN   EXCLUSIVE MODE'
y no recibía ningún error, la tabla ya era de uso exclusivo de mi proceso,
que nadie podía molestar a mi proceso y que al resto de procesos debían de
esperar para iniciarse o les daría un error al iniciar, pero mi sorpresa es
que mi proceso recibe un deadlock y el resto termina bien.

Seguramente tu proceso necesita examinar otras tablas.

Yo creo que deberías hacer que tu proceso de clausura no requiera que no
se inserten movimientos nuevos, sino sólo que no se inserten movimientos
anteriores al timestamp del cierre.


En le proceso de cierre trabajo con dos tablas ,

una que inserta en la tabla de movimientos un regitro por articulo, almacen y otra en la que detallo contenedores y lotes

movimientos

...
id              serial,  (primary key)
id_articulo     integer,
id_almacen      integer,
fecha           date,
unidades        numeric
.....


contenedores

....
id                      serial, (primary key)
id_movimientos          integer, (foreign key de movimientos)
id_contenedor           integer,
id_lote                 integer,
unidades                integer





como tengo que hacer todos los articulos y sus contenedores hago esto

BEGIN
LOCK TABLE movimientos IN   EXCLUSIVE MODE
LOCK TABLE contendores IN   EXCLUSIVE MODE



        cursor con las sumas hasta la fecha por articulo, almacen

                inserto en movimientos ...
                
                
                cursor con los contenedores

                        inserto los contenedores

                end cursor

        end cursor

COMMIT
        


Si alguien intenta meter un movimiento es cuando me da el deadlock.
No se si el problema esta en los campos SERIAL.
Podría hacer un begin por cada articulo, pero la verdad es que prefería hacerlo para todos.




















-
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