1. 程式人生 > >MySql悲觀鎖與樂觀鎖區別及使用場景

MySql悲觀鎖與樂觀鎖區別及使用場景

一、概念上的區別

  樂觀鎖( Optimistic Locking):顧名思義,對加鎖持有一種樂觀的態度,即先進行業務操作,不到最後一步不進行加鎖,"樂觀"的認為加鎖一定會成功的,在最後一步更新資料的時候再進行加鎖。

  悲觀鎖(Pessimistic Lock):正如其名字一樣,悲觀鎖對資料加鎖持有一種悲觀的態度。因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

二、實現方式

樂觀鎖:

  version方式:一般是在資料表中加上一個資料版本號version欄位,表示資料被修改的次數,當資料被修改時,version值會加一。當執行緒A要更新資料值時,在讀取資料的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當前資料庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
sql實現程式碼:

update table 
set x=x+1, version=version+1 
where id=#{id} and version=#{version};

  CAS操作方式:即compare and swap 或者 compare and set,
涉及到三個運算元,資料所在的記憶體值,預期值,新值。當需要更新時,判斷當前記憶體值與之前
取到的值是否相等,若相等,則用新值更新,若失敗則重試,一般情況下是一個自旋操作,即不
斷的重試。

悲觀鎖:

  是由資料庫自己實現的,要用的時候,我們直接呼叫資料庫的相關語句就可以了(原理:共享資源每次只給一個執行緒使用,其它執行緒阻塞,用完後再把資源轉讓給其它執行緒),如行鎖、讀鎖和寫鎖等,都是在操作之前加鎖,在Java中,synchronized的思想也是悲觀鎖。

三、使用場景

樂觀鎖:

  比較適合讀取操作比較頻繁的場景,如果出現大量的寫入操作,資料發生衝突的可能性就會增大,為了保證資料的一致性,應用層需要不斷的重新獲取資料,這樣會增加大量的查詢操作,降低了系統的吞吐量。

悲觀鎖:

  比較適合寫入操作比較頻繁的場景,如果出現大量的讀取操作,每次讀取的時候都會進行加鎖,這樣會增加大量的鎖的開銷,降低了系統的吞吐量。

四、特點

樂觀鎖:

  樂觀鎖的特點先進行業務操作,不到萬不得已不去拿鎖。即“樂觀”的認為拿鎖多半是會成功的,因此在進行完業務操作需要實際更新資料的最後一步再去拿一下鎖就好。

悲觀鎖:

  悲觀鎖的特點是先獲取鎖,再進行業務操作,即“悲觀”的認為獲取鎖是非常有可能失敗的,因此要先確保獲取鎖成功再進行業務操作。通常所說的“一鎖二查三更新”即指的是使用悲觀鎖。

簡而言之記得一句話:讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。樂觀鎖不能解決髒讀的問