間隙鎖詳解

2021-10-07 14:33:25 字數 3173 閱讀 7692

間隙鎖(gap lock)是innodb在 可重複讀 提交下為了解決幻讀問題時引入的鎖機制,(下面的所有案例沒有特意強調都使用可重複讀隔離級別)幻讀的問題存在是因為新增或者更新操作,這時如果進行範圍查詢的時候(加鎖查詢),會出現不一致的問題,這時使用不同的行鎖已經沒有辦法滿足要求,需要對一定範圍內的資料進行加鎖,間隙鎖就是解決這類問題的。在可重複讀隔離級別下,資料庫是通過行鎖和間隙鎖共同組成的(next-key lock),來實現的

加鎖規則有以下特性,我們會在後面的案例中逐一解釋:

案例資料

id(主鍵)

c(普通索引)

d(無索引)55

5101010

1515

1520

2020

2525

25以上資料為了解決幻讀問題,更新的時候不只是對上述的五條資料增加行鎖,還對於中間的取值範圍增加了6間隙鎖,(-∞,5](5,10](10,15](15,20](20,25](25,+supernum] (其中supernum是資料庫維護的最大的值。為了保證間隙鎖都是左開右閉原則。)

步驟事務a

事務b1

begin;

select * from t where id = 11 for update;-2

-insert into user value(12,12,12)

blocked 3

commit;

-當有如下事務a和事務b時,事務a會對資料庫表增加(10,15]這個區間鎖,這時insert id = 12 的資料的時候就會因為區間鎖(10,15]而被鎖住無法執行。

步驟事務a

事務b1

begin;

select * from t where id = 9 for update;-2

-begin;

select * from t where id = 6 for update;3-

insert into user value(7,7,7)

blocked 4

insert into user value(7,7,7)

blocked -

不同於寫鎖相互之間是互斥的原則,間隙鎖之間不是互斥的,如果乙個事務a獲取到了(5,10]之間的間隙鎖,另乙個事務b也可以獲取到(5,10]之間的間隙鎖。這時就可能會發生死鎖問題,如下案例。

事務a獲取到(5,10]之間的間隙鎖不允許其他的ddl操作,在事務提交,間隙鎖釋放之前,事務b也獲取到了間隙鎖(5,10],這時兩個事務就處於死鎖狀態

步驟事務a

事務b事務c

1begin;

update u set d= d+ 1 where id = 7;--

2-insert into u (8,8,8);

blocked -

4--update set d = d+ 1 where id = 10

1.加鎖的範圍是(5,10]的範圍鎖

2.由於資料是等值查詢,並且表中最後資料id = 10 不滿足id= 7的查詢要求,故id=10 的行級鎖退化為間隙鎖,(5,10)

3.所以事務b中id=8會被鎖住,而id=10的時候不會被鎖住

步驟事務a

事務b事務c

1begin;

select id form t where c = 5 lock in share mode;--

2-update t set d = d + 1 where id = 5-4

--insert into values (7,7,7)

blocked 步驟

事務a事務b

事務c1

begin;

select * form t where id >= 10 and id <11 for update--

2-insert into values(8,8,8)

insert into values(13,13,13)

blocked -

4--update t set d = d+ 1 where id = 15

blocked

next-key lock 增加範圍鎖(5,10]

根據原則5,唯一索引的範圍查詢會到第乙個不符合的值位置,故增加(10,15]

因為等值查詢有id =10 根據原則3間隙鎖公升級為行鎖,故剩餘鎖[10,15]

因為查詢並不是等值查詢,故[10,15]不會退化成[10,15)

故事務b(13,13,13)阻塞,事務c阻塞

步驟事務a

事務b事務c

1begin;

select * form t where c >= 10 and c <11 for update--

2-insert into values(8,8,8)

blocked -

4--update t set d = d+ 1 where c = 15

blocked

next-key lock 增加範圍鎖(5,10],(10,15]

因為c是非唯一索引,故(5,10]不會退化為10

因為查詢並不是等值查詢,故[10,15]不會退化成[10,15)

所以事務b和事務c全部堵塞

上面的資料增加一行(30,10,30),這樣在資料庫中存在的c=10的就有兩條記錄

步驟事務a

事務b事務c

1begin;

delete from t where c = 10--

2-insert into values(12,12,12)

blocked -

4--update t set d = d+ 1 where c = 15ok

next-key lock 增加範圍鎖(5,10],(10,15]

因為是等值查詢故退化為(5,10],(10,15),故事務b阻塞,事務c執行成功

加鎖的範圍如下圖

步驟事務a

事務b事務c

1begin;

delete from t where c = 10 limit 2--

2-insert into values(12,12,12)ok

-4--

update t set d = d+ 1 where c = 15ok

根據上面案例8改造,將delete增加limit操作2的操作

因為知道了資料加鎖值加2條,故在加鎖(5,10]之後發現已經有兩條資料,故後面不在向後匹配加鎖。所以事務b執行成功,加鎖範圍如下

詳解mysql間隙鎖

1.什麼是間隙鎖?1 對於鍵值在條件範圍內但並不存在的記錄 在相等條件下請求給乙個不存在的記錄也會加鎖 叫做 間隙 gap innodb也會對這個 間隙 加鎖,這種鎖機制就是所謂的間隙鎖 next key鎖 2 查詢使用的範圍條件不是相等條件,innodb會給符合條件的已有資料記錄的索引項加鎖 2....

mysql間隙鎖 mysql間隙鎖

前面一文 mysql鎖 介紹了mysql innodb儲存引擎的各種鎖,本文介紹一下innodb儲存引擎的間隙鎖,就以下問題展開討論 1.什麼是間隙鎖?間隙鎖是怎樣產生的?2.間隙鎖有什麼作用?3.使用間隙鎖有什麼隱患?一 間隙鎖的基本概念 1.什麼叫間隙鎖 當我們用範圍條件而不是相等條件檢索資料,...

mysql 間隙鎖 mysql間隙鎖 轉

前面一文 mysql鎖 介紹了mysql innodb儲存引擎的各種鎖,本文介紹一下innodb儲存引擎的間隙鎖,就以下問題展開討論 1.什麼是間隙鎖?間隙鎖是怎樣產生的?2.間隙鎖有什麼作用?3.使用間隙鎖有什麼隱患?一 間隙鎖的基本概念 1.什麼叫間隙鎖 當我們用範圍條件而不是相等條件檢索資料,...