間隙鎖(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.什麼叫間隙鎖 當我們用範圍條件而不是相等條件檢索資料,...