mysql間隙鎖 mysql的間隙鎖

2021-10-25 14:51:30 字數 2449 閱讀 2437

最近學習了mysql的各種鎖,有點暈,打算通過文章的方式捋一捋。

在學習了mvcc後,我就想,他已經很好的解決了併發讀寫了,但我也知道innodb提供了多種型別的鎖,所以很好奇這些鎖有什麼用,為什麼這些鎖的功能是mvcc做不到的?(本文討論的都是rr級別下的鎖)

我先建立乙個表,並插入幾行資料,如下圖:

插入內容如下:

c欄位加了普通索引,d欄位無索引。

此時,開啟session a,開始乙個事務,搜尋d=5的記錄,同時開始session b執行更新操作,session c執行插入操作。

現象:session b 的update和session c的 insert都被阻塞了,注意,並沒有直接返回錯誤。

為什麼會被阻塞呢?

因為session a用了select  for update這個鎖,是排他鎖。

在研究這個排他鎖之前,我先從語義上來理解select * from t where d=5 for update的含義。 這句sql的含義是鎖住d=5的行嗎?也許是的。其實也是的。但是這裡有個問題,如果不存在的行,怎麼控制呢?session a一次事務中多次執行elect * from t where d=5 for update我們是不是希望得到同樣的記錄(除非本事務內自己修改)?如果只是鎖住了d=5這行,那麼session b的update和session c的insert就會在session a的事務進行時插入、更新,這樣session a會後面select for update會發現多出來了d=5的行,和第一次不一樣,這就破壞了session a鎖的宣告。這就是幻讀。

什麼是幻讀?

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

在可重複讀隔離級別下,普通的查詢是快照讀,是不會看到別的事務插入的資料的。因此,幻讀在「當前讀」下才會出現。

上面 session b 的修改結果,被 session a 之後的 select 語句用「當前讀」看到,不能稱為幻讀。幻讀僅專指「新插入的行」。

怎麼解決呢?

通過上面的討論我們得知通過給d=5這行加鎖是不行的,那麼如果我們給所有掃瞄的記錄都加鎖能解決這個問題嗎?如果這樣,update語句會被阻塞,但是insert語句依然可以執行成功,因為insert這行是新的行,我們並沒有辦法給他加鎖。也就是說,即使把所有的記錄都加上鎖,還是阻止不了新插入的記錄

到底如何解決?

接下來,我們再看看 innodb 怎麼解決幻讀的問題。

我們知道行鎖只能鎖住現有的行,阻止update,但是不能阻止新的行插入,所以innodb引入了間隙鎖gap lock,這樣在其他session 執行select * for update時,插入操作就會被block。

下圖就是六條記錄,並且形成了7個間隙,因此有7個間隙鎖。

由於d沒有索引,所以所有掃瞄到的行和間隙都會加上鎖,此時其他session就不能做任何插入和更新操作了。為了減小鎖的粒度,一般需要在索引上做select for update,比如select * from t where c=5 for update。

我們知道,行鎖分為讀和寫兩類鎖,那麼同乙個記錄寫行鎖和寫行鎖是衝突的,這符合行鎖的語義。間隙鎖呢?不同session的對同乙個間隙加鎖,會衝突嗎?先來分析一下間隙鎖的語義,比如(5,10)這個間隙鎖,語義是阻止5-10內的插入。所以不同的session對同乙個間隙加鎖是服務語義的,不衝突。當然也會導致死鎖。比如如下順序操作:

上圖的執行順序會造成死鎖:

1、session a先鎖住了(5,10),然後session b 也鎖住了(5,10)。

2、session b試圖插入(9, 9, 9),但是他和session a的間隙鎖衝突了,所以會被block

3、接下來session 試圖插入(9, 9, 9),和session b的間隙鎖衝突,也會被block,就形成了死鎖。

間隙鎖的引入解決了rr級別下的幻讀,但是也導致鎖的範圍變大了,不同時刻,同乙個select 語句可能鎖住不同的間隙,的確影響了併發度,但這也是無奈之舉。行鎖加上間隙鎖就是next-key-lock,當select * from t where c=x for update,這個x在表中時就會加next-key-lock。

值得注意的是,只有rr才有間隙鎖,讀提交的情況下,是不會有間隙鎖的,因為提交後必須被讀到,隔離性沒那麼好。

mysql間隙鎖 mysql間隙鎖

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

mysql 間隙鎖 mysql間隙鎖 轉

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

MySQL的間隙鎖

你好,我是god jiang 接上篇的mysql行鎖,我分享了rc隔離級別下的各種常見情況的加鎖分析。這次分享的是mysql間隙鎖,分析rr隔離級別下各種常見情況的加鎖分析。create table test id int 11 notnull a int 11 notnull b int 11 n...