摘要:樂觀鎖樂觀鎖實際上是一種邏輯思想,并不是數(shù)據(jù)庫的特性。悲觀鎖利用了存儲引擎的支持行鎖的特性。建議在用戶并發(fā)量不大的應用場景下,采用樂觀鎖的方式。在對數(shù)據(jù)一致性要求很高的情況下,可以犧牲一下性能,采用悲觀鎖。
MySQL5.5 版本之后默認采用innoDb 數(shù)據(jù)引擎.本文采用默認的存儲引擎。樂觀鎖
樂觀鎖實際上是一種邏輯思想,并不是mysql 數(shù)據(jù)庫的特性。這個要區(qū)分清楚。 實現(xiàn)數(shù)據(jù)版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。
使用方式::
/** 偽代碼 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){//高并發(fā)下會導致超賣 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時,因為字段不能為負數(shù),將會返回false
悲觀鎖指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當前的其他事務,以及來自外部系統(tǒng)的事務處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機制(也只有數(shù)據(jù)庫層提供的鎖機制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實現(xiàn)了加鎖機制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。悲觀鎖利用了MySQL innoDB 存儲引擎的支持行鎖的特性。一行一行操作數(shù)據(jù).
使用方式:
// 使用悲觀鎖鎖住當前行 $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 行鎖是基于索引來執(zhí)行的,where 條件后必須有索引,不然走的就是全表掃描。
優(yōu)點與不足:
悲觀并發(fā)控制實際上是“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓數(shù)據(jù)庫產(chǎn)生額外的開銷,還有增加產(chǎn)生死鎖的機會;另外,在只讀型事務處理中由于不會產(chǎn)生沖突,也沒必要使用鎖,這樣做只能增加系統(tǒng)負載;還有會降低了并行性,一個事務如果鎖定了某行數(shù)據(jù),其他事務就必須等待該事務處理完才可以處理那行數(shù)樂觀并發(fā)控制相信事務之間的數(shù)據(jù)競爭(datarace)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產(chǎn)生任何鎖和死鎖。但如果直接簡單這么做,還是有可能會遇到不可預期的結(jié)果,例如兩個事務都讀取了數(shù)據(jù)庫的某一行,經(jīng)過修改以后寫回數(shù)據(jù)庫,這時就遇到了問題。
建議: 在用戶并發(fā)量不大的應用場景下,采用樂觀鎖的方式。在對數(shù)據(jù)一致性要求很高的情況下,可以犧牲一下性能,采用悲觀鎖。這個兩種方式的前提是采用MySQL的解決方案。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/31279.html
摘要:并發(fā)同步控制遇到并發(fā)時,我們避免不了要談并發(fā)控制。它會阻塞其它的線程執(zhí)行,如果當前線程一直持有的監(jiān)控鎖,就會把其它線程一直阻塞下去。如果此時線程和線程同時進入方法,用一段語言描述方法的執(zhí)行過程,可能是這樣子。 并發(fā)同步控制 遇到并發(fā)時,我們避免不了要談并發(fā)控制。在Java語言中,我們談并發(fā)時,要談到Object的監(jiān)控鎖。在MySQL的數(shù)據(jù)庫并發(fā)中,我們也要談到mysql的鎖機制。 這樣...
閱讀 794·2021-11-12 10:36
閱讀 3373·2021-09-08 10:44
閱讀 2745·2019-08-30 11:08
閱讀 1402·2019-08-29 16:12
閱讀 2673·2019-08-29 12:24
閱讀 896·2019-08-26 10:14
閱讀 683·2019-08-23 18:32
閱讀 1173·2019-08-23 17:52