悲觀鎖與樂觀鎖

去參加企業(yè)面試,技術(shù)面當(dāng)中關(guān)于數(shù)據(jù)庫這個問題算是高頻問題了,所以在這篇文章中我們一起來搞清楚這兩個概念。

什么是鎖

我們知道數(shù)據(jù)庫是用來存儲數(shù)據(jù)的,傳統(tǒng)的SQL數(shù)據(jù)庫的內(nèi)容存儲在數(shù)據(jù)庫庫表中,一條數(shù)據(jù)就是數(shù)據(jù)庫的一行。

數(shù)據(jù)庫同時提供給多個線程或進(jìn)程訪問,用來做數(shù)據(jù)庫內(nèi)容的增刪改查,當(dāng)多個進(jìn)程或線程對同一條數(shù)據(jù)進(jìn)行操作時,就可能出現(xiàn)如下問題:

丟失更改:

假如存在以下線程:

線程1從數(shù)據(jù)庫取出數(shù)據(jù)并將值加1存回數(shù)據(jù)庫。

線程2從數(shù)據(jù)庫取出數(shù)據(jù)并將值減1存回數(shù)據(jù)庫。

假設(shè)當(dāng)時數(shù)據(jù)庫值為1,兩條線程同時執(zhí)行,則有1號線程執(zhí)行結(jié)果為2,2號線程執(zhí)行結(jié)果為0,無論數(shù)據(jù)庫存哪個結(jié)果,都會丟失另一個線程的執(zhí)行結(jié)果。

臟讀:

線程1修改了數(shù)據(jù),隨后線程2又讀出該數(shù)據(jù),但線程1因為某些原因取消了對數(shù)據(jù)的修改,數(shù)據(jù)恢復(fù)原值,此時線程2得到的數(shù)據(jù)就與數(shù)據(jù)庫內(nèi)的數(shù)據(jù)產(chǎn)生了不一致 。

不可重復(fù)讀:

線程1讀取數(shù)據(jù),隨后線程2讀出該數(shù)據(jù)并修改,此時線程1再讀取數(shù)據(jù)時發(fā)現(xiàn)前后兩次的值不一致 。

可以看出不加任何控制的并發(fā)執(zhí)行可能出現(xiàn)任何無法預(yù)料的結(jié)果,所以需要對數(shù)據(jù)庫修改進(jìn)行限制,在一段時間內(nèi)禁止用戶做某些操作以避免產(chǎn)生數(shù)據(jù)不一致,這就是鎖。

悲觀鎖

它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度(悲觀),因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。 悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制 (也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。

執(zhí)行過程

在對任意記錄進(jìn)行修改前,先嘗試為該記錄加上排他鎖(exclusive locking)。

如果加鎖失敗,說明該記錄正在被修改,那么當(dāng)前查詢可能要等待或者拋出異常。 具體響應(yīng)方式由開發(fā)者根據(jù)實際需要決定。

如果成功加鎖,那么就可以對記錄做修改,事務(wù)完成后就會解鎖了。

其間如果有其他對該記錄做修改或加排他鎖的操作,都會等待我們解鎖或直接拋出異常。

優(yōu)點(diǎn)與不足

悲觀并發(fā)控制實際上是“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全提供了保證。但是在效率方面,處理加鎖的機(jī)制會讓數(shù)據(jù)庫產(chǎn)生額外的開銷,還有增加產(chǎn)生死鎖的機(jī)會;另外,在只讀型事務(wù)處理中由于不會產(chǎn)生沖突,也沒必要使用鎖,這樣做只能增加系統(tǒng)負(fù)載;還有會降低了并行性,一個事務(wù)如果鎖定了某行數(shù)據(jù),其他事務(wù)就必須等待該事務(wù)處理完才可以處理那行數(shù)據(jù)。

樂觀鎖

樂觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。

實現(xiàn)方式

相對于悲觀鎖,在對數(shù)據(jù)庫進(jìn)行處理的時候,樂觀鎖并不會使用數(shù)據(jù)庫提供的鎖機(jī)制。一般的實現(xiàn)樂觀鎖的方式就是記錄數(shù)據(jù)版本。

數(shù)據(jù)版本,為數(shù)據(jù)增加的一個版本標(biāo)識。當(dāng)讀取數(shù)據(jù)時,將版本標(biāo)識的值一同讀出,數(shù)據(jù)每更新一次,同時對版本標(biāo)識進(jìn)行更新。當(dāng)我們提交更新的時候,判斷數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息與第一次取出來的版本標(biāo)識進(jìn)行比對,如果數(shù)據(jù)庫表當(dāng)前版本號與第一次取出來的版本標(biāo)識值相等,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容