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.
--
/
/