mysql鎖 innodb間隙鎖死鎖分析

2021-09-07 20:41:58 字數 3568 閱讀 8111

前言:

在上篇裡分析了一次mysql死鎖問題,後來又深入研究了下死鎖的其他場景,innodb間隙鎖場景下也可能會發生死鎖,所以進一步鞏固下間隙鎖的知識

gap鎖定義:
1.gap就是索引樹中插入新記錄的空隙

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