秒懂INNODB的锁
今天我們來聊聊MySQL中InnoDB存儲引擎的鎖。
鎖是數據庫系統系統區別于文件系統的一個關鍵特性。
lock和 latch
latch
latch在MySQL中是用來保證并發多線程操作操作臨界資源的鎖,鎖定的對象線程,是和咱們使用的Java等傳統語言中的鎖意義相近,而且沒有死鎖檢測的機制。
lock
lock是MySQL中在事務中使用的鎖,鎖定的對象是事務,來鎖定數據庫中表、頁、行;通常只有在事務commit或者rollback后進行釋放。lock是有死鎖機制的,當出現死鎖時,lock有死鎖機制來解決死鎖問題:超時時間(參數innodb_lock_wait_timeout)、wait-for graph。
我們通常講的MySQL的“鎖”,一般就是說的lock。
以下就是InnoDB中“鎖”的大分類:
lock的種類
MySQL Lock大體上可以分為:表鎖、行鎖、意向鎖三種。
共享/排他鎖
行鎖分為:S Lock和X Lock。S Lock :讀鎖;X Lock:寫鎖。 兩鎖之間的兼容性如下。
X S X 不兼容 不兼容 S 不兼容 不兼容復制代碼簡單總結為:讀鎖可以讀,讀鎖不可寫;寫鎖不可讀也tm不可寫。
意向鎖
InnoDB支持多粒度的鎖,即:允許表鎖和行鎖同時存在。 但是,假如表鎖覆蓋了行鎖的數據,所以表鎖和行鎖也會產生沖突。如:
trx1 BEGItrx1 給 T1 加X鎖修改數據。trx2 BEGINtrx2 給 T1 加表鎖修改表結構 復制代碼這樣,表鎖和行鎖之間就產生了沖突,為了解決這種表鎖和行鎖共存的問題,就產生了意向鎖這個東西。 意向鎖:從字面意思也很好理解,就是提前表明一個“意向”。
意向鎖分為:
- 意向共享鎖。它預示著,事務有意向對表中的"某些行"加S鎖。select xxxx lock in share mode,要設置IS鎖。
- 意向排他鎖。它預示著,事務有意向表中的“某些行”加X鎖。select xxx for update,要設置IX鎖。
但意向鎖僅僅是表明意向,它其實非常弱,意向鎖之間可以相互并行,并不是排斥的: 意向鎖之間的兼容性問題:
IS IXIS 兼容 兼容IX 兼容 兼容 復制代碼但是,意向鎖可以和行鎖互斥。
S XIS 兼容 互斥不兼容IX 互斥不兼容 互斥不兼容復制代碼于是,上述現象就變為了:
trx1 BEGINtrx1 給 T1 先加IX ,然后在某一行記錄加X鎖。trx2 BEGINtrx2 給 T1 加表鎖(事務被阻塞,等待加鎖成功)trx2 修改表結構 復制代碼主鍵自增鎖
自增鎖(auto-inc Locks)是一種特殊的表級鎖,專門針對事務插入AUTO_INCREMENT類型的列,往往就是主鍵列。可以保證主鍵的值自增是“原子操作”,不會出現一致性、唯一性問題。
行鎖的具體分類
InnoDB存儲引擎有以上3種行鎖算法。以上3種,都是實現在索引上的。
記錄鎖(Record Lock)
記錄鎖(Record Lock)總是會去鎖住索引記錄。 假如沒有任何一個索引,那么InnoDB會鎖住隱形創建的那個主鍵。
注意:這里鎖的是索引,不一定只是主鍵索引哦,還可能是二級普通索引。
間隙鎖(Gap Lock)
顧名思義,它會封鎖索引記錄中的“縫隙”,讓制其他事務在“縫隙”中插入數據。 它鎖定的是一個不包含索引本身的范圍。
例如以下索引數據:
間隙鎖(Gap Lock)可以鎖的將是以下范圍
具體的范圍還要根據查詢條件不同而定。 間隙鎖開啟的事務隔離級別是 Repeatable Read,如果把數據庫事務級別降為Read Committed(默認是 Repeatable Read),間隙鎖則會自動失效。
臨鍵鎖(Next-Key Lock)
Next-Key Lock可以說是記錄鎖(Record Lock)和間隙鎖(Gap Lock)的組合,既封鎖了"縫隙",又封鎖了索引本身。
還是上面的索引數據:
臨鍵鎖(Next-Key Lock)鎖住的范圍將是:
Next-key Lock在索引具有唯一性的時候,例如主鍵索引的數據,將會降級為記錄鎖(Read Lock),以增加并發性。 例如:
T1 T2BEGIN; | select * From T | where id = 5 for update | ---------------------------------------------------------------| BEGIN; | Insert into t (4, xx); --------------------------------------------------------------- | COMMIT| ----------------------------------------------------------------COMMIT | || ----------------------------------------------------------------- 復制代碼以上情況,就會把Next-key Lock降級為記錄鎖(Read Lock)
再談不可重復讀(No Reaptable Read)和幻讀(Phantom Problem)
有些很權威的書中認為這倆是同一個概念,例如:<<MySQL技術內幕 InnoDB存儲引擎>>。 但是就目前網絡上的眾多總結和個人看法,認為區別如下:
不可重復讀:修改。在同一個事務中,主要是說多次讀取一條記錄, 發現該記錄中某些列值被修改過。 幻讀:增加或者刪除。在同一個事務中,同一條完全相同的查詢語句返回的結果集行數不同。
參考:https://stackoverflow.com/questions/11043712/what-is-the-difference-between-non-repeatable-read-and-phantom-read
認真的說,多版本并發控制 MVCC(讀)和 臨鍵鎖 Next-Key Lock(寫)共同解決了幻讀問題。
關于MVCC的原理,就是每份數據會有快照,事務中讀取數據(簡單的select xxx from,select xx from xx for update或者select xx from xxx in share mode不行)的時候,如果數據被鎖住了,就讀以前留下的快照數據。在此不過多贅述了。
以下為多版本并發控制原理圖
MVCC只在Read Committed和Repeatable Read下會開啟。但是在這兩種隔離級別下對于快照指定的數據定義不同。
在Read Committed下,MVCC讀取的是被鎖定數據的最新的一份數據。 在Repeatable Read下,MVCC讀取的是事務剛開始時候的數據。
更多精彩內容,請關注我的微信公眾號 互聯網技術窩 或者加微信共同探討交流:
總結
以上是生活随笔為你收集整理的秒懂INNODB的锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RESTful API 中的 Statu
- 下一篇: 开工的欲望 | AI Studio上线新