探索Mysql鎖機制(二)——共享鎖&排他鎖&意向鎖&間隙鎖
MileStone
上一篇,我們講了Mysql的 樂觀鎖和悲觀鎖 ,大家有興趣可以連起來一起看。
本文需要閱讀時間大約在 1小時 ,請抽出完整的時間來閱讀,拒絕一目十行。
後面會按照下圖,分批次對Mysql的鎖和大家一起分享

image.png
:hibiscus:花絮

image.png
:eyeglasses: 仔細看哦 :eyeglasses:
今天採蜜採到一份看起來不錯的簡歷,正襟危坐,電話call過去。
對方的電話響著粵語版的《明年今日》,讓我想起了村裡的小芳,鞭子粗又長。
“喂,哪位?”,對方的聲音很Young很有錢。
“同學你好,我是巴巴的面試官,你對XX巴巴有興趣嗎,現在方不方便聊聊?”。
“...你好,有啊,方便的。”
“okay,那我們簡單的聊一會,你能先簡單的介紹一下自己嗎?”。
“好,我叫小明,在OO上班,工作3年,無房無車,有個女朋友叫清風...”
吧啦吧啦......
“專案用到了SpringBoot、MQ、Mysql...”
“好的,那我們聊一聊mysql的鎖吧!”。
1. Mysql的事務
偉人說:“想了解一件事情,你就得了解它的前因後果”,
想了解透徹mysql的鎖,不得不說mysql的事務機制。
於是我問小明:你對mysql的事務瞭解嗎?
小明輕咳一下,娓娓道來:
1.1 事務概述
資料庫事務是資料庫執行過程中的一個邏輯單位,一個事務通常包含了對資料庫的讀/寫操作。它的存在包含有以下兩個目的:
- 為資料庫操作序列提供了一個回滾的方法,同時提供了資料庫即使在異常狀態下仍能保持一致性的方法。
- 當多個應用程式在併發訪問資料庫時,可以在這些應用程式之間提供一個 隔離方法 (版面問題下次討論),以防止彼此的操作互相干擾。
1.2 事務的特性:ACID
- 原子性 aotmic
事務必須是原子工作單元;對於其資料修改,要麼全都執行,要麼全都不執行。
- 一致性 consistent
事務在完成時,必須使所有的資料都保持一致狀態。
- 隔離性 isolaton
由併發事務所作的修改必須與任何其它併發事務所作的修改隔離。事務檢視資料時資料所處的狀 態,要麼是另一併發事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會檢視中間狀態的資料
- 永續性 duration
事務完成後,它對系統的影響是永久性的
2. 排他鎖&共享鎖
我心想,這個誰都懂,繼續追問:那你能在講講鎖嗎?
好的,那我講一下Mysql的幾個鎖。小明竊喜,我已經看了 imooc(公眾號微信) 大神的鎖了,我怕你?
2.1 共享鎖(shared locks,S鎖)
小明說:在你沒有女朋友的時候,你想和女人滾床單時候,只能去找紅燈區,別人也可以找紅燈區,這就是共享!
共享鎖又叫讀鎖,如果事務T1對行R加上S鎖,則
- 其它事務T2/T3/Tn只能對行R再加S鎖,不能加其它鎖
- 獲得S鎖的事務只能讀資料,不能寫資料(你傻呀,當然也不能刪咯)。
select … lock in share mode;
2.2 排他鎖(exclusive locks,X鎖)
小明說:你有錢找了個女票,你就要獨佔這個女票,別人不能使用,看(讀)都不行!這就是排他!我們重點說一下排它鎖。
排它鎖又叫寫鎖,如果事務T1對行R加上X鎖,則
- 其它事務T2/T3/Tn都不能對行R加任何型別的鎖,直到T1事務在行R上的X鎖釋放。
- 獲得X鎖的事務既能讀資料,又能寫資料(也可以刪除資料)。
select ... for update
舉例表USER:
id | name | desc |
---|---|---|
1 | 馬雲 | 首富 |
2 | 小明 | 首負 |
T1(事務1):
// start T1 SELECT * FROM USER WHERE id = 1 lock in share mode; (S鎖) ...... // start T2 UPDATE USER SET name = '小明' WHERE id = 1; ......
如果T1不進行提交,則S鎖不會釋放,
那麼T2就拿著X鎖眼巴巴的看著,一直等待T1(事務1)釋放S鎖。
此時
// 接上文程式碼塊 // start T3 // 此時,如果 T3 做同樣查詢,可以直接獲取S鎖進行查詢 SELECT * FROM USER WHERE id = 1 lock in share mode; (S鎖) 這個時候如果T1(事務1)要進行 DELETE 操作 // start T1 SELECT * FROM USER WHERE id = 1 lock in share mode; (S鎖) ...... DELETE FROM USER WHERE id = 1; ......
此時:
T1發現X鎖被T2佔據著,所以T1拿不到X鎖一直等待T2釋放X鎖,而T2拿著X鎖等待T1釋放S鎖,這樣互相等待就產生了死鎖,deadLock。
發生死鎖以後,InnoDB 會產生錯誤資訊,並且釋放鎖( 後面會專門講業務中遇到的死鎖和解決方案 )。
上述X鎖的程式碼可以用下圖來顯示:

image.png
用時間流程來顯示3個執行緒的互動如下:

image.png
你可以把排它鎖對行的保護,看作你對你女的保護,只能你碰,別人不能動!前提你得有女, 不認真學習,你就是個屌絲...單身狗
聽到這裡我覺得小明同學很有意思哦,這個栗子:chestnut:舉得很有力氣很有代入感!不愧是有女朋友的人啊!
3. 意向鎖
我對小明已經開始有點興趣了,繼續追問,那你能否再說一下意向鎖?
好!
3.1 意向鎖(Intention Locks)
小明說: 他在找蒼老師或者女票時候,先要遠端看看對方有沒有被人家共享或者獨佔,而不是到面前有沒有人鎖住她,可以節省成本!
意向鎖是表鎖,多用在innoDB中,是資料庫自身的行為,不需要人工干預,在事務結束後會自行解除。
意向鎖分為意向共享鎖(IS鎖)和意向排它鎖(IX鎖)
- 鎖:表示事務中將要對某些行加S鎖
- IX鎖:表示事務中將要對某些行加X鎖
意向鎖的主要作用是提升儲存引擎效能,innoDB中的S鎖和X鎖是行鎖, 每當事務到來時,儲存引擎需要遍歷所有行的鎖持有情況,效能較低 ,因此 引入意向鎖 ,檢查行鎖前先檢查意向鎖是否存在,如果存在則阻塞執行緒。
3.2 意向鎖的使用
順上面的思路講下去,我們看下使用的邏輯
舉個栗子:chestnut::
T1: SELECT * FROM A WHERE id = 1 lock in share mode;(加S鎖) T2: SELECT * FROM A WHERE id > 0 for update; (加X鎖)
看上面這2個SQL事務,T1執行時候,對id=1這行加上了S鎖,T2執行前,需要獲取全表的更新鎖進行判斷,即:
step1:判斷表A是否有表級鎖
step2:判斷表A每一行是否有行級鎖
當資料量較大時候(我們一張表一般500-5000萬資料), step2這種判斷極其低效 。
亞麻跌!亞麻跌!亞麻跌!於是乎,我們就need意向鎖協議。
意向鎖協議
- 事務要獲取表A某些行的S鎖必須要獲取表A的IS鎖
- 事務要獲取表A某些行的X鎖必須要獲取表A的IX鎖
Now!do you get me sense ?
這個時候 step2 就改變成了對意向鎖的判斷
step2:發現表A有IS鎖,說明表肯定有行級的S鎖,因此,T2申請X鎖阻塞等待,不需要判斷全表,判斷效率極大提高(是不是省了很多錢)
4. 間隙鎖
小明先飈了一段英語,想來壓制我?
但是我並不care,who care? 9012 年了,誰不會英語?so easy!我可是從小用步步高點讀機長大的人哦。
我say: pardon ? (上小學我就會,小樣,你再飈啊!)
4.0 官方原文:

image.png
A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record. For example, SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; prevents other transactions from inserting a value of 15 into column t.c1, whether or not there was already any such value in the column, because the gaps between all existing values in the range are locked.
當我們用範圍條件條件檢索資料(非聚簇索引、非唯一索引),並請求共享或排他鎖時,InnoDB會給符合條件的資料記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,稱為間隙,InnoDB也會為這些間隙加鎖,即間隙鎖。
Next-Key鎖是符合條件的行鎖加上間隙鎖
4.1 間隙鎖產生的條件
在InnoDB下,間隙鎖的產生需要滿足三個條件:
- 隔離級別為RR
- 當前讀
- 查詢條件能夠走到索引
4.2 間隙鎖的作用
MySQL官方文件:間隙鎖的目的是為了讓其他事務無法在間隙中新增資料。
在RR模式的InnoDB中,間隙鎖能起到兩個作用:
1. 保障資料的恢復和複製
2. 防止幻讀
- 防止在間隙中執行insert語句
- 防止將已有資料update到間隙中
資料庫資料的恢復和複製是通過binlog實現的, binlog中記錄了執行成功的DML語句(在阿里得到了極廣泛的應用) ,在資料恢復時需要保證資料之間的事務順序,間隙鎖可以避免在一批資料中插入其他事務。
對於間隙鎖,筆者人為,你只要能get到上述英語片段的點,就Okay了,小學5年級就能讀懂,如果讀不懂,你真的要去學一下英語了,不會英語的程式設計師,一定是個最low逼的程式設計師!
廣而告之
最後,做個廣告,現在阿里開放為數不多的HC,如果有想來的同學,給我私聊,幫你內推哦~簡歷飛來吧,同學們。
和小明的故事還在繼續,他又回去看 imooc 的公眾號去了,很快就會回來。