Postgresql

驗證新訂單的可用性

  • April 13, 2021

我有一個來自 Web 界面的倉庫批發商的銷售、庫存和付款管理應用程序。特別是,當一個訂單被執行時,它必須創建一個對應於每個訂購了相應數量的產品的行。庫存可用性的驗證是在下訂單時完成的。

考慮以下兩種訂單驗證方式:

  1. BEFORE INSERT在 table 上使用觸發器,在驗證是否有足夠的庫存OrderLine時執行 SELECT 。Product
  2. 做一個SELECT ... FROM OrderLine JOIN Product WHERE quant < stock

我的問題是:這兩種選擇中的哪一種更可取,為什麼/在什麼情況下?

我只看到你SELECT在兩種變體中都做 a 。如果您想確保您的銷售量不會超過您的庫存(庫存),您必須在下訂單的同一筆交易中減少您的庫存。對作業使用數據修改 CTE(Postgres 9.1 或更高版本):

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;

CTE 中的 僅在產品有足夠庫存的UPDATE情況下才返回值(並且它在行上具有寫鎖定)。在這種情況下,就在下訂單之前,在同一筆交易中減少了數量。

將所有訂單詳細資訊放入一個事務中,如果其中任何一個失敗,INSERTROLLBACK

可能的死鎖

這種情況很容易導致死鎖。假設您有兩個訂單同時進來,都想要產品 A 和 B。第一個訂單以 A 開頭,第二個訂單以 B 開頭。然後兩個交易相互阻止。每個都等待另一個完成。出現僵局

在 PostgreSQL 中,事務會在被鎖停止時等待一段時間。根據您的設置deadlock_timeout(預設為 1 秒),將執行可能的死鎖檢查。

一旦檢測到,就會中止一個事務並報告死鎖異常。另一個可以完成。哪一個很難預測。

有一個簡單的方法可以避免這種死鎖:始終將您order_details順序保持一致。喜歡訂購的產品product_id。這樣,上述情況永遠不會發生。

引用自:https://dba.stackexchange.com/questions/12731