1. 程式人生 > >鎖機制--事務鎖、樂觀鎖、悲觀鎖

鎖機制--事務鎖、樂觀鎖、悲觀鎖

檢視mysql隔離級別:

select @@tx_isolation;
show variables like '%tx_isolation%';

事務的四種隔離級別

set session transaction isolation level 隔離級別

1. read uncommitted : 讀取尚未提交的資料:哪個問題都不能解決
2. read committed:讀取已經提交的資料 :可以解決髒讀 ---- oracle預設 會出現不可重複讀,幻讀
3. repeatable read:重讀讀取:可以解決髒讀和不可重複讀 ---mysql預設的,無法解決幻讀
4. serializable:序列化:可以解決髒讀、不可重複讀和幻讀---相當於鎖表

serializable隔離級別下,所有select語句都會被隱式的轉化為select …lock in share mode.這可能導致,如果有未提交的事務正在修改某些行,所有讀取這些行的select都會被阻塞住。

show variables like '%iso%'版本控制很強,在設定set global transaction isolation level read committed;時無法更改當前會話,可以在修改全域性變數後修改會話set session transaction isolation level read committed;類似重新載入變數

驗證隔離級別操作步驟

開始驗證之前,需要知道,MySQL預設開啟autocommit,預設隔離級別為repeatable read,MySQL事務的流程為begin ...end
在事務執行過程中,採用MVCC解決不可重複讀問題。事務在預設隔離級別下,多版本控制資料庫DML操作。

在模擬實驗時需設定autocommit=off,方便模擬

順序 事務1 事務2
1 begin;
2 begin;
3 select * from sakila2.actor1 where actor_id=2;
4 select * from sakila2.actor1 where actor_id=2;
5 update sakila2.actor1 set first_name=‘kdd1’ where actor_id=2;
6 commit;
7 select * from sakila2.actor1 where actor_id=2;
8 select * from sakila2.actor1 where actor_id=2;
9 update sakila2.actor1 set first_name=‘kdd1’ where actor_id=2;
10 commit;
11 select * from sakila2.actor1 where actor_id=2;
12 select * from sakila2.actor1 where actor_id=2;
13 end;
14 end;

樂觀鎖和悲觀鎖

當我們說樂觀鎖和悲觀鎖時,它們的概念和事務鎖(共享鎖、排它鎖)是完全不同的。
樂觀鎖和悲觀鎖是針對應用和資料庫之間的一種取數和鎖定策略。而事務鎖是資料庫為了解決資料庫一致性問題出現的解決方案。這一點很重要。
所謂樂觀鎖,就是利用版本號比較機制,只是在讀資料的時候,將讀到的資料的版本號一起讀出來,當對資料的操作結束後,準備寫資料的時候,再進行一次資料版本號的比較,若版本號沒有變化,即認為資料是一致的,沒有更改,可以直接寫入,若版本號有變化,則認為資料被更新,不能寫入,防止髒寫。版本號一般通過加欄位的方式來實現,可以是自增標識,也可以是時間戳。

搶購執行過程

說明:以上為操作執行過程簡要描述

多使用者搶購衝突

說明:如上圖所示,如果更新操作順序執行,則資料的版本(version)依次遞增,不會產生衝突。但是如果發生有不同的業務操作對同一版本的資料進行修改,那麼,先提交的操作(圖中B)會把資料version更新為2,當A在B之後提交更新時發現數據的version已經被修改了,那麼A的更新操作會失敗。

悲觀鎖是以悲觀的態度面對高併發,此時高併發如果採用樂觀鎖會經常導致修改出現等待的情況。
在應用設計和儲存過程開發時,應以最小代價方式選擇樂觀鎖和悲觀鎖。一般b/s環境下,推薦使用樂觀鎖 。

高併發多修改,為什麼使用悲觀鎖?

從下例中可以看出假設只是進行一次修改。
樂觀鎖的操作除了case1其餘均返回錯誤。此時開銷為5次查詢,1次加鎖,1次修改。悲觀鎖只有case1可以執行,其餘均處於等待狀態。此時開銷為,1次查詢,1次加鎖,1次更新。所以使用悲觀鎖開銷更小。

樂觀鎖

case 1 case 2 case 3 case 4 case 5
update table set update table set update table set update table set update table set
success failure failure failure failure
返回資訊 下一步操作 下一步操作 下一步操作 下一步操作

悲觀鎖

case 1 case 2 case 3 case 4 case 5
update table set 等待操作 等待操作 等待操作 等待操作
success failure failure failure failure
返回資訊 獲取鎖 獲取鎖 獲取鎖 獲取鎖