前言:gap鎖定義:在上篇裡分析了一次mysql死鎖問題,後來又深入研究了下死鎖的其他場景,innodb間隙鎖場景下也可能會發生死鎖,所以進一步鞏固下間隙鎖的知識
1.gap就是索引樹中插入新記錄的空隙gap鎖作用:2.相應的gap鎖就是加在gap上的鎖
防止幻讀,通過間隙鎖阻止特定條件的新記錄的插入,後面單獨就那些驗證幻讀現象注意:
1. 只在repeatable read隔離級別下的特定操作才會取得gap lock
2. update/delete/select for update時,除了對唯一索引的唯一搜尋外都會獲取gap鎖,也就是說主鍵或唯一索引的搜尋不會獲取間隙鎖,當然如果查詢條件還包含非唯一索引,那麼還是會獲取間隙鎖
模擬間隙鎖死鎖場景:
一、前置條件:
1.建立表:
create table `test_gap_table` (
`primary_no` char(16) not null comment '主鍵號',
`index_no` char(16) not null comment '索引號',
primary key (`primary_no`),
key(`index_no`)
) engine=innodb default charset=utf8 comment='測試間隙表';
2.插入測試資料:
insert into `test_gap_table` values ('1', 'a');
insert into `test_gap_table` values ('3', 'c');
insert into `test_gap_table` values ('5', 'd');
insert into `test_gap_table` values ('7', 'e');
二、模擬死鎖:
開啟事務1:
##開啟事務1
start transaction;
## 獲取間隙鎖,鎖定範圍(a,d)
update test_gap_table set index_no='c' where index_no='c';
## 休息10秒,執行事務2
select sleep(10);
## 執行insert,插入到事務2的間隙鎖鎖定範圍中
insert into test_gap_table(primary_no, index_no) values('7', 'e');
截圖:
開啟事務2:
##開啟事務2
start transaction;
## 獲取間隙鎖,鎖定範圍(d, d後面的無窮大)
update test_gap_table set index_no='e' where index_no='e';
## 執行insert,插入到事務1的間隙鎖鎖定範圍中
insert into test_gap_table(primary_no, index_no) values('2', 'b');
截圖:
三、結果:
事務1休息完十秒後,事務2出現死鎖:
四、死鎖分析:
因為index_no是非唯一索引,所以執行事務1更新語句時獲取了間隙鎖,鎖定範圍是非唯一索引的上下區間,即(a,d)
事務1休息,執行事務2更新語句獲取間隙鎖,鎖定範圍為(d, d後面的無窮大),然後執行事務2insert語句,因為事務1鎖定了(a,d)範圍,所以insert操作會等待事務1釋放間隙鎖
事務1休息結束,執行insert語句,恰好插入的資料在事務2鎖定的間隙鎖範圍,這樣就導致事務1和事務2迴圈等待了,死鎖發生
五、間隙鎖鎖定原理:
執行update/delete/select for update,會產生間隙鎖
innodb會根據更新或查詢的索引條件,尋找非唯一索引的間隙鎖的上下區間,例如:
update test_gap_table set index_no=『c』 where index_no=『c』;
因為index_no為非唯一索引,所以尋找』c』字元在表test_gap_table中記錄的上下區間,上區間為:a,下區間為:d
如果插入資料在區間之內,則無法插入,因為被間隙鎖鎖定;如果插入資料在區間的邊界值,此時需要根據主鍵來判斷鎖定範圍,接著2中例子:
1):如果index_no是a,則取a的最大主鍵值為』1』,只要插入的主鍵
2):如果index_no是d,則取d的最小主鍵值為』5』,只要插入的主鍵》'5』則可以自由插入,主鍵
模擬rr隔離級別下幻讀:
1.建立表:
create table `test_rr_unreal` (
`id` bigint(20) not null auto_increment,
`index_no` int(10) default null,
primary key (`id`)
) engine=innodb auto_increment=0 default charset=utf8;
2.插入資料:
insert into `test_rr_unreal` values ('1', '100');
3.在mysql命令列下開啟乙個事務a,執行查詢操作:
4.在mysql命令列下開啟另乙個session,執行更新操作:
5.在事務a下,執行更新操作:
6.在事務a下,執行查詢操作:
結果:在事務a中,預期是基於查詢結果101,但是被另乙個事務的更新操作影響到了最終預期結果,違反了repeatable read的承諾,看到了事務開始後其它事務的併發更新,出現幻讀。
分析:雖然rr隔離級別下看到的是事務開始時的快照,在update/delete操作下,是可以看到另乙個事務提交的操作的。
InnoDB間隙鎖簡介
mysql innodb支援三種行鎖定方式 行鎖 record lock 也叫記錄鎖,鎖直接加在索引記錄上面。間隙鎖 gap lock 鎖加在不存在的空閒空間,可以是兩個索引記錄之間,也可能是第乙個索引記錄之前或最後乙個索引之後的空間。next key lock 行鎖與間隙鎖組合起來用就叫做next...
mysql間隙鎖 mysql間隙鎖
前面一文 mysql鎖 介紹了mysql innodb儲存引擎的各種鎖,本文介紹一下innodb儲存引擎的間隙鎖,就以下問題展開討論 1.什麼是間隙鎖?間隙鎖是怎樣產生的?2.間隙鎖有什麼作用?3.使用間隙鎖有什麼隱患?一 間隙鎖的基本概念 1.什麼叫間隙鎖 當我們用範圍條件而不是相等條件檢索資料,...
mysql 間隙鎖 mysql間隙鎖 轉
前面一文 mysql鎖 介紹了mysql innodb儲存引擎的各種鎖,本文介紹一下innodb儲存引擎的間隙鎖,就以下問題展開討論 1.什麼是間隙鎖?間隙鎖是怎樣產生的?2.間隙鎖有什麼作用?3.使用間隙鎖有什麼隱患?一 間隙鎖的基本概念 1.什麼叫間隙鎖 當我們用範圍條件而不是相等條件檢索資料,...