1. 程式人生 > >MySQL處理高併發,防止庫存超賣庫存出現負數

MySQL處理高併發,防止庫存超賣庫存出現負數

mysql處理高併發的方式比較多,以下為比較簡單的一種(mysql事物控制)
beginTranse();
try{
$result = $dbca->query('select amount from s_store where postID = 12345');
if(result->amount > 0){
//quantity為請求減掉的庫存數量
$dbca->query('update s_store set amount = amount - quantity where postID = 12345');
}
}catch($e Exception){
rollBack('');

}
commit();
// 咋一看此方法貌似沒有問題,但如果仔細看會發現這個方法是不可取的
// 比如你購買商品的數量是大於1的此時如果庫存只剩下1 執行庫存就會出現負數的情況
// 就算是商品庫存大於1 當有大量的請求擠進事物時會產生一個共享鎖,所以在select的時候查詢出來的結果都是滿足條件的
// 這個時候update更新語句會把併發序列化,也就是給同時到達這裡的update語句排個序,
// 一個一個執行,並生成排他鎖,在當前這個update語句commit之前,其他使用者等待執行,commit後,生成新的版本;這樣執行完後,庫存肯定為負數了。
// 所有我們需要一個小小的改動:
beginTranse();
try{
//quantity為請求減掉的庫存數量,先減去庫存

$dbca->query('update s_store set amount = amount - quantity where postID = 12345');
$result = $dbca->query('select amount from s_store where postID = 12345');
if(result->amount < 0){
throw new Exception('庫存不足');
}
}catch($e Exception){
rollBack(回滾)
}
commit(提交事務)
簡化後:
beginTranse(開啟事務)
try{
//quantity為請求減掉的庫存數量

$dbca->query('update s_store set amount = amount - quantity where amount>=quantity and postID = 12345');
}catch($e Exception){

rollBack();

}

commit();