MySQL 樂觀鎖於悲觀鎖

MySQL5.5 版本以後默認採用innoDb 數據引擎.本文采用默認的存儲引擎。

樂觀鎖

樂觀鎖其實是一種邏輯思想,並非mysql 數據庫的特性。這個要區分清楚。
實現數據版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。

使用方式:mysql

/** 僞代碼  number 庫存  goods_id 商品ID  version 版本號默認爲0 **/

$sql="select number from goods where goods_id={$goods_id} and version= {$version} ";

// 時間戳方式查詢庫存
$sql="select number from goods where goods_id={$goods_id} and time < time() ";

$rs=mysqli_query($conn,$sql);

$row = $rs->fetch_assoc();

if($row['number']>0){//高併發下會致使超賣

    if($row['number']<$number){

        return insertLog('庫存不夠',3,$username);
    }

//庫存減小
 $sql="update goods set number=number-{$number},version += 1 where goods_id={$goods_id}  and number>0";

// 時間戳方式減小庫存
$sql="update goods set number=number-{$number},time = time() where goods_id={$goods_id}  and number>0";

$store_rs=mysqli_query($conn,$sql);

if($store_rs){

//生成訂單,返回操做成功
                    
echo json_encode(array('code'=>0,'msg'=>'庫存減小成功','data'=>$username));

}else{
   echo json_encode(array('code'=>1,'msg'=>'庫存減小失敗','data'=>$username));
}
}else{
    echo json_encode(array('code'=>3,'msg'=>'庫存減小失敗','data'=>$username));
}
注意:使用樂觀鎖須要注意啊,將庫存字段number字段設爲unsigned,當庫存爲0時,由於字段不能爲負數,將會返回false

悲觀鎖

悲觀鎖指的是對數據被外界(包括本系統當前的其餘事務,以及來自外部系統的事務處理)修改持保守態度,所以,在整個數據處理過程當中,將數據處於鎖定狀態。悲觀鎖的實現,每每依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,不然,即便在本系統中實現了加鎖機制,也沒法保證外部系統不會修改數據)。

悲觀鎖利用了MySQL innoDB 存儲引擎的支持行鎖的特性。一行一行操做數據.sql

使用方式:數據庫

// 使用悲觀鎖鎖住當前行
$sql="select number from goods where goods_id={$goods_id} for update ";

// 減小庫存操做
$sql="update goods set number=number-{$number} where goods_id={$goods_id}  and number>0";
注意:innoDB 行鎖是基於索引來執行的,where 條件後必須有索引,否則走的就是全表掃描。

優勢與不足json

悲觀併發控制其實是「先取鎖再訪問」的保守策略,爲數據處理的安全提供了保證。可是在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,還有增長產生死鎖的機會;另外,在只讀型事務處理中因爲不會產生衝突,也不必使用鎖,這樣作只能增長系統負載;還有會下降了並行性,一個事務若是鎖定了某行數據,其餘事務就必須等待該事務處理完才能夠處理那行數

樂觀併發控制相信事務之間的數據競爭(datarace)的機率是比較小的,所以儘量直接作下去,直到提交的時候纔去鎖定,因此不會產生任何鎖和死鎖。但若是直接簡單這麼作,仍是有可能會遇到不可預期的結果,例如兩個事務都讀取了數據庫的某一行,通過修改之後寫回數據庫,這時就遇到了問題。安全

建議: 在用戶併發量不大的應用場景下,採用樂觀鎖的方式。在對數據一致性要求很高的狀況下,能夠犧牲一下性能,採用悲觀鎖。這個兩種方式的前提是採用MySQL的解決方案。併發

相關文章
相關標籤/搜索