在商城中,有一件商品有100件庫存,那么用戶每購買一件,庫存要做減一。 剛開始我想到這樣進行處理:
$model = new Model();
//讀取商品的庫存
$ = $model->where(" id = 1 ")->count();
//庫存減一
$--;
$result = ("UPDATE goods SET = $ WHERE id = 1 ");
這樣的方式,在不考慮并發(fā)的情況下是沒問題的,但如果有多個用戶同時操作,情況就不一樣了。
假設(shè)兩個用戶同時購買,A用戶讀取庫存為10,B用戶讀取庫存也是10,A購買完成后,將庫存減一,改為9, 而此時,B也將庫存減一,改為9。實際賣出了兩件,但庫存沒有正確減少,就會造成“超賣”。
A、B用戶的購買流程是交叉執(zhí)行的。
問題的關(guān)鍵在于上面的代碼使用了兩條SQL語句,所以造成了不同用戶的請求可能交叉執(zhí)行。 如果能將操作合并到一條SQL語句中,就可以避免這個問題。
請看修改后的代碼:
$model = new Model();
$result = ("UPDATE goods SET = - 1 WHERE id = 1 ");
由于關(guān)系型數(shù)據(jù)庫都是存儲在文件中,對同一條記錄的修改不能同時進行。這意味著即使A、B用戶同時購買,修改庫存時也是按先后順序來的,因此庫存可以正確的減少。
還有一個問題,如果庫存已經(jīng)為0了,上面的代碼就有問題了,因為沒有檢查庫存。
有兩種方法解決該問題:
1、將字段設(shè)為,當庫存為0時,因為字段不能為負數(shù),將會返回false。
2、修改SQL語句和實現(xiàn)代碼:
$model = new Model();
//讀取商品的庫存
$ = $model->where(" id = 1 ")->count();
//庫存減一
$--;
$result = ("UPDATE goods SET = - 1 WHERE id = 1 WHERE > 0 ");
$num = ();
if($num == 1){
//成功
} 如果庫存為0了,受影響的行將為0,意味著購買失敗。