今天咱們來聊聊MySQL中InnoDB存儲引擎的鎖。算法
鎖是數據庫系統系統區別於文件系統的一個關鍵特性。數據庫
latch
在MySQL中是用來保證併發多線程操做操做臨界資源的鎖
,鎖定的對象線程,是和我們使用的Java等傳統語言中的鎖意義相近,並且沒有死鎖檢測的機制。bash
lock
是MySQL中在事務中使用的鎖
,鎖定的對象是事務,來鎖定數據庫中表、頁、行;一般只有在事務commit或者rollback後進行釋放。lock是有死鎖機制的,當出現死鎖時,lock有死鎖機制來解決死鎖問題:超時時間(參數innodb_lock_wait_timeout
)、wait-for graph
。微信
咱們一般講的MySQL的「鎖」,通常就是說的lock。網絡
如下就是InnoDB中「鎖」的大分類:多線程
MySQL Lock大致上能夠分爲:表鎖、行鎖、意向鎖三種。併發
行鎖分爲:S Lock
和X Lock
。S Lock
:讀鎖;X Lock
:寫鎖。 兩鎖之間的兼容性以下。ui
X S
X 不兼容 不兼容
S 不兼容 兼容
複製代碼
簡單總結爲:讀鎖能夠讀,讀鎖不可寫;寫鎖不可讀也tm不可寫。
spa
InnoDB支持多粒度的鎖,即:容許表鎖和行鎖同時存在。 可是,假如表鎖覆蓋了行鎖的數據,因此表鎖和行鎖也會產生衝突。如:線程
trx1 BEGI
trx1 給 T1 加X鎖修改數據。
trx2 BEGIN
trx2 給 T1 加表鎖修改表結構
複製代碼
這樣,表鎖和行鎖之間就產生了衝突,爲了解決這種表鎖和行鎖共存的問題,就產生了意向鎖
這個東西。 意向鎖:從字面意思也很好理解,就是提早代表一個「意向」。
意向鎖分爲:
意向共享鎖
。它預示着,事務有意向對錶中的"某些行"加S鎖。select xxxx lock in share mode
,要設置IS
鎖。意向排他鎖
。它預示着,事務有意向表中的「某些行」加X鎖。select xxx for update
,要設置IX
鎖。但意向鎖僅僅是代表意向,它其實很是弱,意向鎖之間能夠相互並行,並非排斥的: 意向鎖之間的兼容性問題:
IS IX
IS 兼容 兼容
IX 兼容 兼容
複製代碼
可是,意向鎖能夠和行鎖互斥。
S X
IS 兼容 互斥不兼容
IX 互斥不兼容 互斥不兼容
複製代碼
因而,上述現象就變爲了:
trx1 BEGIN
trx1 給 T1 先加IX ,而後在某一行記錄加X鎖。
trx2 BEGIN
trx2 給 T1 加表鎖(事務被阻塞,等待加鎖成功)
trx2 修改表結構
複製代碼
自增鎖(auto-inc Locks
)是一種特殊的表級鎖,專門針對事務插入AUTO_INCREMENT
類型的列,每每就是主鍵列。能夠保證主鍵的值自增是「原子操做」,不會出現一致性、惟一性問題。
InnoDB存儲引擎有以上3種行鎖算法。以上3種,都是實如今索引上的。
記錄鎖(Record Lock)老是會去鎖住索引記錄。 假如沒有任何一個索引,那麼InnoDB會鎖住隱形建立的那個主鍵。
注意:這裏鎖的是索引,不必定只是主鍵索引哦,還多是二級普通索引。
顧名思義,它會封鎖索引記錄中的「縫隙」,讓制其餘事務在「縫隙」中插入數據。 它鎖定的是一個不包含索引自己的範圍。
例如如下索引數據:
間隙鎖(Gap Lock)
能夠鎖的將是如下範圍
具體的範圍還要根據查詢條件不一樣而定。 間隙鎖開啓的事務隔離級別是 Repeatable Read
,若是把數據庫事務級別降爲Read Committed
(默認是 Repeatable Read
),間隙鎖則會自動失效。
Next-Key Lock
能夠說是記錄鎖(Record Lock
)和間隙鎖(Gap Lock
)的組合,既封鎖了"縫隙",又封鎖了索引自己。
仍是上面的索引數據:
臨鍵鎖(Next-Key Lock)
鎖住的範圍將是:
Next-key Lock
在索引具備惟一性的時候,例如主鍵索引的數據,將會降級爲記錄鎖(Read Lock)
,以增長併發性。 例如:
T1 T2
BEGIN; |
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存儲引擎>>。 可是就目前網絡上的衆多總結和我的見解,認爲區別以下:
不可重複讀
:修改。在同一個事務中,主要是說屢次讀取一條記錄, 發現該記錄中某些列值被修改過。 幻讀
:增長或者刪除。在同一個事務中,同一條徹底相同的查詢語句返回的結果集行數不一樣。
參考:stackoverflow.com/questions/1…
認真的說,多版本併發控制 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
讀取的是事務剛開始時候的數據。
互聯網技術窩
或者加微信共同探討交流: