Re: Update concurrente

From: Horacio Miranda <hmiranda(at)gmail(dot)com>
To: Silvio Bravo Cadó <bravocado(at)gmail(dot)com>, postgre sql <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: Update concurrente
Date: 2019-12-06 03:53:14
Message-ID: 2eb9d469-972e-5de9-4903-f2c872c692b1@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda


On 5/12/2019 2:46 PM, Silvio Bravo Cadó wrote:
> Hola lista,
Hola disculpa por no contestar antes.
> Espero se encuentren muy bien, les escribo porque tengo una duda con
> respecto a si estoy realizando bien las actualizaciones en una tabla o
> tal vez sea algo del diseño de la solución.
> Tengo una tabla A que busca llevar el inventario de productos, que
> podría describirse así:
>
> Id                   int
> nombre          text
> precio            numeric(8,2)
> cantidad         int
> disponibilidad int
>
> Cada vez que se crea un nuevo registro se define la cantidad y la
> disponibilidad que son las mismas. También se tiene un check
> constraint donde cantidad >= disponibilidad.
>
> Por otro lado cuando se tiene otra tabla B que representa las compras:
>
> Id                  int
> producto_id   int
>
> Cada vez que se agrega un registro en B se ejecuta un trigger que hace
> un update a A para restar disponibilidad con un: UPDATE A SET
> disponibilidad = disponibilidad - 1 WHERE id = New.id
>
> El problema es que estas tablas pueden tener mucha concurrencia,
> muchos usuarios finales intentando comprar y por temporalidad compran
> el mismo producto y cuando hay picos de usuarios el update puede
> llegar a tardar hasta 60 segundos o mas en completarse.

En registro Civil de Chile teníamos algo similar, terminamos creando una
tabla llamada , Por Procesar, ejemplo. productos_pp (donde un job en la
base de datos se encarga de mover los datos dentro de la base de datos).

La gracia para no tener bloqueos es que ese update de disponibilidad sea
con un commit inmediato debes tener un indice por product_id para
generar bloqueos solo en un producto y luego liberarlo bien rápido.

select for update, update, delete y commit debe ocurrir bien rapido, no
a la espera de un cliente que termine una transacción, para ganar
velocidad debes usar tablas temporales y al final de cada transacción se
re-confirma la transacción.

Ejemplo, en order cronológico.

Tablas, Ventas, ventas_pp, Productos, productos_pp, Compras.

1.- Stock 10 manzanas(1), 20 bananas(2).30 naranjas(3).

2.- usuario A, selecciona stock id=1,cantidad,5 ( al seleccionarlas
inserta una linea en producto_pp por cada item que agrega a un carrito ).

3.- usuario B, selecciona Stock id=1 cantidad que muestra disponibles 5,
debe mostrar los productos - productos_pp. ( indicando que hay 5 items
en proceso).

Vas captando la idea ? Cuando terminas la transacción procesar la venta
y ahí en ese momento crear un registro en ventas_pp.

4.- El proceso que se ejecuta cada (ejemplo 5 segundos ) toma los
registros en estado final de la tablas _pp y actualiza los productos. de
esa forma no hay bloqueos.

La clave es que las tablas _pp solo hagan inserts. nada de updates, solo
el proceso interno ( que en registro le llamabamos motor) hace los updates.

Otra cosa a considerar es no tener el modelo en forma nomal3, Forma
normal2 se comporta mucho mejor para transacciones masivas.

Espero que esto te ayude.

>
> Mi duda es si hay alguna forma de mejorar el rendimiento de este update.
>
>
> De antemano muchas gracias.
>
>
>
> --
> /
>
> /

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Carlos T. Groero Carmona 2019-12-08 04:21:02 Re: Update concurrente
Previous Message Alvaro Herrera 2019-12-05 19:07:20 Re: Update concurrente