1. 程式人生 > >MYSQL鎖機制詳解

MYSQL鎖機制詳解

最近在學習MySQL的鎖機制和隔離級別,發現跟Oracle還是有比較大的差異。例如Oracle預設隔離級別是read committed,而MySQL預設是repeatable read。Oracle除了序列化,無法避免幻讀。而MySQL在repeatable read級別下,通過next-key鎖機制,避免了幻讀的產生。記錄一下理論理解以及實驗驗證。
InnoDB鎖型別有如下幾種:
共享鎖(S)和排他鎖(X);
意向鎖(Intention locks);
行鎖(Record lock);
間隔鎖(Gap lock);
Next-key lock;
插入意向鎖(Insert Intention lock)
1.共享鎖和排他鎖


InnoDB的行級鎖分為共享鎖和排他鎖。共享鎖(S)鎖定一行用於讀取,排他鎖(X)鎖定一行用於修改寫入。
如果一個事務在一行資料上持有共享鎖(S),其他事務也可以獲取該行上的共享鎖(S),這種情況是多個事務同時持有該行資料的共享鎖(S);但其他無法獲取該行上的排他鎖(X)。
如果一個事務在一行資料上持有排他鎖(X),其他事務無法獲取該行以上兩種型別的鎖。
同時,InnoDB的行鎖是通過索引實現的,如果列上沒有索引,那麼鎖的粒度是表級的。
實驗:t1表的id列上沒有索引
在這裡插入圖片描述
在這裡插入圖片描述
2.意向鎖
InnoDB支援多粒度鎖,允許同時存在表鎖和行鎖(但各種型別鎖之間有衝突限制,後面會說明),引入了意向鎖。意向鎖是表級別的,在獲取行鎖之前,會先申請一個意向鎖,表示之後該事務會在某些行上申請行鎖。意向鎖有兩種型別:
1)共享意向鎖(IS),表示事務將在某些資料行上持有共享鎖;
2)排他意向鎖(IX),表示事務將在某些資料行上持有排他鎖。
例如,select … for share持有共享意向鎖(IS),select … for update持有排他意向鎖(IX)。
意向鎖機制約定如下:
1)一個事務獲取共享行鎖前,必須先獲取共享意向鎖(IS);
2)一個事務獲取排他行鎖前,必須先獲取排他意向鎖(IS)。
意向鎖及行鎖之間的相容性如下:
在這裡插入圖片描述

當事務申請一個鎖時,不管是意向鎖還是行鎖,都要看是否與已存在的鎖是否相容。可以通過show engine innodb status\G檢視意向鎖的事務資訊。
3.行鎖
行鎖是通過鎖定索引行來實現的。同樣可以通過show engine innodb status\G檢視行鎖的事務資訊。
4.間隔鎖
間隔鎖用來鎖定一個區間內的索引行,或者鎖定索引第一個值以前和最後一個值往後的區間。例如
SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;
將會在鎖定10<=c1<=20的區間,阻塞c1=15的插入,不管表上是否已存在c1=15。
間隔鎖對單值也同樣有效。
但如果列上有唯一索引,就不會用到間隔鎖,而是隻鎖定指定的行。
間隔鎖是效能和併發性的折中,如果將隔離級別設為read committed,即禁用間隔鎖,但在外來鍵和重複鍵約束檢查的時候,仍然會啟用間隔鎖。
間隔鎖實驗在後面next-key鎖一起演示。
5.next-key鎖

next-key鎖是行鎖和間隔鎖的結合,即鎖住該行資料及該行資料往前的區間。MySQL就是通過next-key鎖避免了幻讀的產生。
例如ti表id列上有10, 11, 13, and 20這些值,那麼可能的next-key鎖區間會是以下:
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
實驗:
1)id列上沒有索引,則select id from id=11 for update是鎖表的,前文已經有過說明;
2)id列上有索引,
當id是11,會鎖住(10,11]
在這裡插入圖片描述
在這裡插入圖片描述
當id是索引最小值10,會鎖住(negative infinity, 10];當id是索引最大值20,會鎖住(20, positive infinity),即id=13也不能插入。
next-key鎖小結:
next-key總會鎖住資料行本身(行鎖)以及該行的前一個索引行對應的資料行(間隔鎖);
當選定條件包含索引最小值,則包含鎖住小於索引最小值的無窮區間;
當選定條件包含索引最大值,則包含鎖住大於索引最大值的無窮區間。

實驗:next-key鎖避免幻讀,以下實驗中隔離級別是read committed,無論是用for share 還是for update鎖住id>13的資料行,還是可以往表裡插入id=23的資料,那麼再發起同樣查詢的時候,就肯定會出現不一樣的結果,像是出現了幻覺一樣。以下就省略for update的測試了。
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
6.插入意向鎖
插入意向鎖是一種間隔鎖,作用在插入行及行往前的區間,只要插入的資料行不衝突,不同事物之間的插入意向鎖即使在區間上重疊,也不會產生等待。