Pregunta

Tengo una aplicación de gestión de ventas, acciones y pago en un almacén entero desde una interfaz web. En particular, cuando se efectúa un pedido, debe crear una línea correspondiente a cada producto ordenado con la cantidad respectiva. La validación de la disponibilidad de acciones se realiza en el momento del pedido.

Teniendo en cuenta las siguientes dos formas de validación en orden:

  1. Use un gatillo BEFORE INSERT en la mesa OrderLine, que hace una selección en Product Verificar que hay suficiente stock.

  2. Hacer un SELECT ... FROM OrderLine JOIN Product WHERE quant < stock.

Mi pregunta es: ¿Cuál de estas dos alternativas es preferible y por qué / para qué escenario?

¿Fue útil?

Solución

Solo te veo haciendo una selección en ambas variantes. Si desea asegurarse de no vender más de lo que tiene en la tienda (acciones), debe disminuir su acción en la misma transacción que realiza el pedido. En PostgreSQL 9.1 Podrías usar un CTE modificador de datos para el trabajo:

WITH u AS (
   UPDATE product SET quant = quant - <put_order_quant_here>
   WHERE  product_id = <order_prod_id>
   AND    quant >= <put_order_quant_here>
   RETURNING product_id, <put_order_quant_here> AS quant
   )
INSERT INTO order_detail (order_id, product_id, quant)
SELECT <put_order_id_here>, product_id, quant
FROM   u;

La actualización en el CTE solo devuelve los valores si el producto tiene stock suficiente. En este caso, la cantidad se reduce en la misma transacción, justo antes de que se realice el pedido.

Ponga todas las colas de pedido en una transacción, si alguna de ellas no puede insertar, ROLLBACK.


Posibles plazos

Un consejo más: este escenario podría conducir fácilmente a los puntos muertos. Digamos que tiene dos pedidos al mismo tiempo, ambos quieren el producto A y B. El primer pedido comienza colocando el orden_detail en A, el segundo comienza con B. Luego las dos transacciones se bloquean entre sí. Cada uno de ellos esperaría a que el otro se complete. A punto muerto se produce.

En PostgreSQL, una transacción esperará algún tiempo cuando esté estancado por cerraduras. Dependiendo de su configuración de deadlock_timeout (El valor predeterminado es 1S, que establecí en al menos 5s en servidores de producción sin problemas), se realizarán verificaciones para una posible condición de punto muerto.

Una vez detectado, se abortará una transacción e informará una excepción de punto muerto. El otro puede terminar. Cuál es difícil de predecir.

Hay una manera simple de evitar este tipo de estlocks: siempre coloque su order_details en un orden consistente. Como productos ordenados por product_id. De esta manera, el escenario anterior nunca puede suceder.

Otros consejos

Actualizar:

Hice esta publicación antes de agregar la etiqueta PostgreSQL, pero los conceptos deberían ser similares. Básicamente, debe poder bloquear el registro de alguna manera para garantizar que el valor de las acciones que seleccione sigue siendo el valor de stock que disminuye. La misma transacción que bloquea el registro debe actualizar el stock e insertar en la tabla de orden. Tan pronto como determine que el stock no está disponible, vuelva a reiniciar toda la transacción.

Si este procesamiento se realiza en una operación por lotes mediante un proceso, entonces no necesita preocuparse por bloquear los registros individuales, pero debe asegurarse de que solo un proceso por lotes se ejecute al mismo tiempo.


Examinar...

  1. los ESPERE cláusula de la instrucción SELECT.
  2. los Colección a granel cláusula de la instrucción SELECT.
  3. los PARA TODOS declaración.

Probablemente también quiera asegurarse de que todas las entradas tuvieran suficientes stock, por lo que es posible que desee que se agregue si las acciones están disponibles o no.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top