樂觀鎖和悲觀鎖

一、悲觀鎖(Pessimistic Concurrency Control),第一眼看到它,相信每一個人都會想到這是一個悲觀的鎖。沒錯,它就是一個悲觀的鎖。mysql

那這個悲觀體如今什麼地方呢?悲觀是咱們人類一種消極的情緒,對應到鎖的悲觀情緒,悲觀鎖認爲被它保護的數據是極其不安全的,每時每刻都有可能變更,一個事務拿到悲觀鎖後(能夠理解爲一個用戶),其餘任何事務都不能對該數據進行修改,只能等待鎖被釋放才能夠執行。sql

數據庫中的行鎖,表鎖,讀鎖,寫鎖,以及syncronized實現的鎖均爲悲觀鎖。數據庫

 

 

 咱們常用的數據庫是mysql,mysql中最經常使用的引擎是Innodb,Innodb默認使用的是行鎖。而行鎖是基於索引的,所以要想加上行鎖,在加鎖時必須命中索引,不然將使用表鎖。安全

 

 

二、 樂觀鎖(Optimistic Concurrency Control)的「樂觀情緒」體如今,它認爲數據的變更不會太頻繁。所以,它容許多個事務同時對數據進行變更。性能

樂觀鎖一般是經過在表中增長一個版本(version)或時間戳(timestamp)來實現,其中,版本最爲經常使用。spa

事務在從數據庫中取數據時,會將該數據的版本也取出來(v1),當事務對數據變更完畢想要將其更新到表中時,會將以前取出的版本v1與數據中最新的版本v2相對比,若是v1=v2,那麼說明在數據變更期間,沒有其餘事務對數據進行修改,此時,就容許事務對錶中的數據進行修改,而且修改時version會加1,以此來代表數據已被變更。命令行

若是,v1不等於v2,那麼說明數據變更期間,數據被其餘事務改動了,此時不容許數據更新到表中,通常的處理辦法是通知用戶讓其從新操做。不一樣於悲觀鎖,樂觀鎖是人爲控制的。code

 

 

 (3)悲觀鎖實現blog

 

 SQL添加 for update索引

select num from goods where id = 1 for update;

原理圖解:

咱們經過開啓mysql的兩個會話,也就是兩個命令行來演示。
一、事務A執行命令給id=1的數據上悲觀鎖準備更新數據

 

 

 

這裏之因此要以begin開始,是由於mysql是自提交的,因此要以begin開啓事務,不然全部修改將被mysql自動提交。

二、事務B也去給id=1的數據上悲觀鎖準備更新數據

 

 

 

咱們能夠看到此時事務B再一直等待A釋放鎖。若是A長期不釋放鎖,那麼最終事務B將會報錯,這有興趣的能夠去嘗試一下。

三、接着咱們讓事務A執行命令去修改數據,讓豬肉脯的數量減一,而後查看修改後的數據,最後commit,結束事務。

 

 

 

咱們能夠看到,此時最後一個豬肉脯被A買走,只剩0個了。


四、當事務A執行完第3步後,咱們看事務B中出現了什麼

 

咱們看到因爲事務A釋放了鎖,事務B就結束了等待,拿到了鎖,可是數據此時變成了0,那麼B看到後就知道被買走了,就會放棄購買。



(4)樂觀鎖實現

思路:

        使用樂觀鎖的解決思路是,咱們認爲數據修改產生衝突的機率並不大,多個事務在修改數據的以前先查出版本號,在修改時把當前版本號做爲修改條件,只會有一個事務能夠修改爲功,其餘事務則會失敗。

demo:

A和B同時將豬肉脯(id=1下面都說是id=1)的數據查出來,而後A先買,A將id=1和version=0做爲條件進行數據更新,即將數量-1,而且將版本號+1。

此時版本號變爲1。A此時就完成了商品的購買。最後B開始買,B也將id=1和version=0做爲條件進行數據更新,可是更新完後,發現更新的數據行數爲0,此時就說明已經有人改動過數據,此時就應該提示用戶從新查看最新數據購買。

 圖解:

 

咱們仍是經過開啓mysql的兩個會話,也就是兩個命令行來演示。

一、事務A執行查詢命令,事務B執行查詢命令,由於二者查詢的結果相同,因此下面我只列出一個截圖。

 

 

 

此時A和B均獲取到相同的數據

二、事務A進行購買更新數據,而後再查詢更新後的數據。

 

 

 

咱們能夠看到事務A成功更新了數據和版本號。

 

事務B再進行購買更新數據,而後咱們看影響行數和更新後的數據  

 

 

能夠看到最終修改行數爲0,數據沒有改變。此時就須要咱們告知用戶從新處理。

 

(5)樂觀鎖和悲觀鎖總結:

悲觀鎖

 

  • 優勢:悲觀鎖利用數據庫中的鎖機制來實現數據變化的順序執行,這是最有效的辦法

  • 缺點:一個事務用悲觀鎖對數據加鎖以後,其餘事務將不能對加鎖的數據進行除了查詢之外的全部操做,若是該事務執行時間很長,那麼其餘事務將一直等待,那勢必影響咱們系統的吞吐量。

 

樂觀鎖

 

  • 優勢:樂觀鎖不在數據庫上加鎖,任何事務均可以對數據進行操做,在更新時才進行校驗,這樣就避免了悲觀鎖形成的吞吐量降低的劣勢。

  • 缺點:樂觀鎖由於是經過咱們人爲實現的,它僅僅適用於咱們本身業務中,若是有外來事務插入,那麼就可能發生錯誤。

(6) 應用場景

 

悲觀鎖:由於悲觀鎖會影響系統吞吐的性能,因此適合應用在寫爲居多的場景下。

樂觀鎖:由於樂觀鎖就是爲了不悲觀鎖的弊端出現的,因此適合應用在讀爲居多的場景下。

相關文章
相關標籤/搜索