MySQL的間隙鎖

2021-10-22 17:26:34 字數 2786 閱讀 5965

你好,我是god-jiang~

接上篇的mysql行鎖,我分享了rc隔離級別下的各種常見情況的加鎖分析。這次分享的是mysql間隙鎖,分析rr隔離級別下各種常見情況的加鎖分析。

create

table

`test`

(`id`

int(11)

notnull

,`a`

int(11)

notnull

,`b`

int(11)

notnull

,`c`

int(11)

notnull

,primary

key(

`id`),

unique

key unix_key(

'a')

,key ix_key(

`b`)

)engine

=innodb

;insert

into test values(0

,0,0

,0),

(5,5

,5,5

),(10

,10,10

,10),

(20,20

,20,20

);

建立一張test表,id是主鍵,a是唯一索引,b是普通索引,c是沒有索引。現在假設是在rc隔離級別下,我們來做乙個實驗看看:

事務a事務b

set session transaction_isolation=『read-committed』;

set session transation_isolation=『read-committed』;

begin;

select * from test where b=5 for update;

返回:(5,5,5,5)

begin;

insert into test values(6,6,5,5);

commit;

select * from test where b=5 for update;

返回:(5,5,5,5),(6,6,5,5)

commit;

由上面實驗得出,在rc隔離級別下,事務a對b=5這一行記錄加了x鎖,但是事務b插入一條新的記錄的b欄位也是為5,然後在事務a中可以查出b=5有兩條記錄,這個就產生了「幻讀」。

也就是說,幻讀是指乙個事務前後兩次查詢同一範圍的時候,後一次查詢看到了前一次查詢沒有看到的行記錄。

為什麼會產生幻讀呢?

我們來分析一下此時rc隔離級別+b普通索引的加鎖情況:

可以看到rc隔離級別下,b=5的記錄加上了x鎖,但是(0,5)還有(5,10)的間隙沒有鎖的情況,所以在這個間隙中可以插入新的資料。

現在我就可以回答出為什麼會產生幻讀了。產生幻讀的原因是,行鎖只能鎖住行,但是新插入記錄的這個動作,要更新的是記錄之間的「間隙」。因此,為了解決幻讀的問題,innodb在rr隔離級別引入了新的鎖,它就是間隙鎖(gap lock)。

上面講了幻讀怎麼產生的,還有innodb引入間隙鎖解決了幻讀的情況,接下來分析一下rr隔離級別的加鎖分析。

這裡我挑選出rc隔離級別下三種常見情況分析sql如何加鎖:

以下演示的表結構是文章開頭的結構,資料是我個人臆想的。

上圖所示,gap鎖加在c欄位的(負無窮,0),(0,5),(5,10),(10,20),(20,正無窮)。但是在rr隔離級別下,我們都是預設是用next-key lock(行鎖+間隙鎖),所以我們都是預設是左開右閉。

總結:rr隔離級別下,無索引的條件欄位的當前讀不僅會把每條記錄都加上x鎖,還會加上gap鎖。再次強調,當前讀或者插入/更新/刪除操作需要加上索引。

如上圖所示,普通索引欄位b=10給兩條記錄加了x鎖,並且把聚集索引樹的兩條記錄也加了x鎖。gap鎖的是b的範圍(5,10),(10,10),(10,正無窮)。所以next-key lock鎖的是(5,10],(10,10],(10,正無窮]。期間只要是b在next-key lock的範圍內就更新全部阻塞。

舉例:insert into test values(6,6,6,6)就會被阻塞,原因就是rr隔離級別的間隙鎖鎖住了記錄之間的「間隙」,所以會阻塞操作。

唯一索引的情況是最簡單的,因為不管是rc隔離級別或者是rr隔離級別,唯一索引都只能查出一條記錄,只會在對應的行記錄加上x鎖就沒了。

為什麼會這樣?

因為gap鎖的目的是為了防止同一事務被連續兩次當前讀,然後兩次讀的情況不一致。如果能夠保證欄位是唯一的(唯一索引),其實就是最多只有一條記錄滿足條件,所以查詢唯一索引的時候絕對不會出現gap鎖。

可以理解為rr+唯一索引和rc+唯一索引的加鎖情況是一樣的就好了。

特別注意:innodb引入的next-key lock只解決了快照讀的幻讀,並沒有解決當前讀的幻讀。

其實next-key lock解決了快照讀的幻讀很大的一部分原因是因為undo log和mvcc,這裡先留個懸念,關於mvcc的分享我會抽空寫出來,並且分享出來。

mysql間隙鎖 mysql的間隙鎖

最近學習了mysql的各種鎖,有點暈,打算通過文章的方式捋一捋。在學習了mvcc後,我就想,他已經很好的解決了併發讀寫了,但我也知道innodb提供了多種型別的鎖,所以很好奇這些鎖有什麼用,為什麼這些鎖的功能是mvcc做不到的?本文討論的都是rr級別下的鎖 我先建立乙個表,並插入幾行資料,如下圖 插...

mysql間隙鎖 mysql間隙鎖

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

mysql 間隙鎖 mysql間隙鎖 轉

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