Re: Duda con cursor + SELECT FOR UPDATE

From: Jorge Sanchez <espartano(dot)mail(at)gmail(dot)com>
To: Lista PostgreSQL <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: Duda con cursor + SELECT FOR UPDATE
Date: 2019-05-21 17:19:59
Message-ID: CAJaC6KZi_uPkBMDKcxA2=TmTiokCTc=T0pyocRi5Nb93_WyevQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

On Tue, May 21, 2019 at 7:13 AM Stephen Amell <mrstephenamell(at)gmail(dot)com> wrote:
>
> Hola,
>
> La funcion es transaccional en si, o sea, que fuera de tu scope no se va
> a ver el bloqueo de registros. Lo tenes que hacer por afuera antes de
> llamar a la funcion, commitear y recien ahi empezar a laburar.

Difiero, al aplicar el SELECT FOR UPDATE dentro del Store procedure he
visto que los registros se bloquean para cualquier transacción no
solamente para la transacción que va dentro de la función, y es
precisamente ese comportamiento el que espero.

>
> for!!!! en una DB!!!!! no se si matarte o abrazarte... ;P

Bueno, recorrer los resultados de un select 1 a 1 en un FOR es
admisible de hecho la base de datos provee los mecanismos necesarios
para esto:

https://www.postgresql.org/docs/9.4/plpgsql-control-structures.html

>
> trata de pasar todo a joins que te va a mejorar la vida.
>

Precisamente estoy eliminando un join que me da problemas por que el
bloqueo de registros con SELECT FOR UPDATE no funciona si tienes
agrupaciones, entonces para mi caso es preferible hacer un select en
la tabla donde voy a actualizar en vez de hacer un join que me da casi
todo el resultado en un paso y luego sobre ese resultado actualizar
los registros que necesito, como esta función la hicieron de esa forma
(con un join y sin los bloqueos necesarios) cuando la base de datos
tiene mucha concurrencia y se lanza el store procedure de forma casi
simultánea (la concurrencia en este caso podría ser valida) los
registros se actualizan de forma concurrente pero los datos pierden
integridad por la forma en que están estructurados (es una base de
datos legada y en producción).

Básicamente el problema que estoy tratando es un problema de entradas
y salidas, voy a tratar de explicarme un poco mejor:

Tengo una tabla IN donde existe un registro por cada entrada de
productos por ejemplo que están asociados a una cuenta, es decir cada
registro en IN pertenece a una cuenta y tiene el numero de productos
que entraron y puede haber multiples registros de entrada, tengo otra
tabla OUT que registra salidas, multiples salidas pueden estar
asociadas a una sola entrada, si hago un join entre estas dos tablas
para sumarisar las salidas que corresponden a una entrada (SUM() +
GROUP BY) no puedo ejecutar SELECT FOR UPDATE en IN para bloquear los
registros de entrada, entonces quité el join y ejecuto un SELECT FOR
UPDATE en IN (obviamente con el respectivo WHERE para seleccionar
todos los registros IN asociados a una cuenta y demás restricciones) y
por cada registro verifico las correspondientes salidas en OUT para
verificar si el registro en IN aún tiene productos remanentes y
cuantos y en base a eso agregar registros en OUT y actualizar el
registro en IN para marcarlo como "agotado", si no realizo el bloqueo
de registros que posiblemente serán actualizados en cada llamada al
store procedure y se ejecuta nuevamente el store procedure la
contabilidad podría verse comprometida, aplicando SELECT FOR UPDATE
entiendo que si se ejecuta el store procedure nuevamente antes de que
termine el primero, el segundo quedará bloqueado (puesto que
posiblemente va a actualizar los mismos registros) hasta que el que
fue lanzado primero termine.

Espero haberme explicado mejor.

> salu2

Saludos.

> On 2019-05-20 20:42, Jorge Sanchez wrote:
> > Buenas tardes lista, tengo la siguiente duda y espero me puedan ayudar
> > a resolverla:
> >
> > Tengo en una función de pl/pgsql un ciclo FOR que itera sobre el
> > resultado de un SELECT con la particularidad de que dicho SELECT tiene
> > la cláusula FOR UPDATE ya que quiero bloquear los registros de dicho
> > SELECT puesto que van a ser actualizados, por algún lugar leí que los
> > ciclos FOR crean implícitamente un cursor para iterar sobre los
> > resultados, mi duda en concreto es si los registros que regresa el
> > SELECT al FOR se marcan como bloqueados al inicio del FOR o se
> > bloquean van siendo cargados en el cursor?
> >
> > Gracias de antemano.
> >
> >
> >

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Arcel Labrada Batista 2019-05-21 20:20:03 Re: Duda con cursor + SELECT FOR UPDATE
Previous Message Jorge Sanchez 2019-05-20 23:42:12 Duda con cursor + SELECT FOR UPDATE