新しい注文の可用性の検証
-
16-10-2019 - |
質問
Webインターフェイスから倉庫全体の販売、株式、支払いの管理アプリケーションがあります。特に、順序が発効する場合、それぞれの数量で注文された各製品に対応する線を作成する必要があります。在庫の可用性の検証は、注文の時点で行われます。
次の2つの検証方法を検討してください。
トリガーを使用します
BEFORE INSERT
テーブルの上OrderLine
, 、それは選択を行いますProduct
十分な在庫があることを確認します。a
SELECT ... FROM OrderLine JOIN Product WHERE quant < stock
.
私の質問は、これらの2つの選択肢のうちどれが望ましいのか、そしてなぜ /どのシナリオのために?
解決
私はあなたが両方のバリエーションでセレクトをしているのを見るだけです。ストア(ストック)よりも多く販売しないようにしたい場合は、注文するのと同じトランザクションで在庫を減らす必要があります。の postgreSQL 9.1 aを使用できます データ修飾CTE 仕事で:
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の更新は、製品に十分な在庫がある場合にのみ値を返します。この場合、注文が行われる直前に、同じトランザクションで数量が減少します。
すべての注文申告を1つのトランザクションに入れます。 ROLLBACK
.
デッドロックの可能性
もう1つのアドバイス:このシナリオは、簡単にデッドロックにつながる可能性があります。たとえば、2つの注文が同時に入っています。両方とも製品AとBが必要です。最初の注文は、Order_DetailをAに配置することから始まります。2番目はBで始まります。次に、2つのトランザクションが互いにブロックされます。それらのそれぞれは、相手が完了するのを待ちます。 a デッドロック その後。
PostgreSQLでは、トランザクションはロックによって停止される場合にしばらく待ちます。の設定に応じて deadlock_timeout
(デフォルトは1秒で、これを非張り合いの生産サーバーで少なくとも5秒に設定しました)、デッドロック条件の可能性をチェックします。
検出されると、1つのトランザクションが中止され、デッドロックの例外が報告されます。もう1つは終了できます。どれが予測するのが難しいですか。
この種のデッドロックを避ける簡単な方法があります:常にあなたを置きます order_details
で 一貫した順序. 。注文した製品のように product_id
. 。これにより、上記のシナリオは決して起こりません。
他のヒント
アップデート:
PostgreSQLタグが追加される前にこの投稿を作成しましたが、概念は似ているはずです。基本的に、選択した株価が減少する株式値のままであることを確認するために、何らかの方法でレコードをロックできる必要があります。レコードをロックするのと同じトランザクションは、ストックを更新し、Orderlineテーブルに挿入する必要があります。在庫が利用できないと判断したらすぐに、トランザクション全体をバックバックします。
この処理が1つのプロセスごとにバッチ操作で行われた場合、個々のレコードのロックに関心を持つ必要はありませんが、1つのバッチプロセスのみが同時に実行できることを確認する必要があります。
調べてください...
また、おそらくすべてのエントリが十分な在庫を確保することを望んでいるので、在庫が利用可能かどうかにかかわらず、一部を集約する必要がある場合があります。