phpは注文・抽選の同時発生による在庫負数の問題を解決する

1205 ワード

データベース処理sqlは、商品を購入するプロセスが次のようになっていると仮定して処理されていることを知っています.
sql 1:商品在庫照会
if(在庫数量>0){//受注生成...sql 2:在庫-1}並行していない場合、上記の流れはこのように完璧に見えます.同時に2人で注文し、在庫は1つしかありません.sql 1段階で2人で照会した在庫はいずれも>0で、最終的にsql 2を実行し、在庫は最後に-1になり、超過販売され、在庫を補充するか、ユーザーの苦情を待つか.
この問題を解決する比較的流行している考え方:
1.追加の単一プロセスで1つのキューを処理し、単一リクエストをキューに入れ、1つずつ処理すれば、同時的な問題はありませんが、追加のバックグラウンドプロセスと遅延の問題は考慮されません.
2.データベース楽観ロック、大体の意味は先に在庫を照会して、それからすぐに在庫を+1して、それから注文が生成した後に、在庫を更新する前にもう一度在庫を照会して、予想の在庫数量と一致しているかどうかを見て、一致しないでロールバックして、ユーザーの在庫不足を提示します.
3.updateの結果から判断すると、sql 2のときに判断条件updateを追加することができます...where在庫>0、falseを返すと在庫不足を示し、トランザクションをロールバックします.
4.ファイル排他ロックを利用して、注文要求を処理する時、flockで1つのファイルをロックして、もしロックに失敗したら他の注文が処理していることを説明して、この時待つか、直接ユーザーに「サーバーが忙しい」と提示するか
本稿では、4つ目のシナリオについて説明します.大まかなコードは以下の通りです.
//ブロック(待機)モード
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))
{
    //..    
    flock($fp,LOCK_UN);
}

fclose($fp);

//非ブロックモード
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
    //..    
    flock($fp,LOCK_UN);
}
else
{
    echo "    ,     ";
}

fclose($fp);

どの方式を採用するかは、同時数量を見てみましょう.