MySQL間隙鎖問題

2021-07-25 18:52:15 字數 2016 閱讀 5028

間隙鎖(gap lock):鎖加在不存在的空閒空間,可以是兩個索引記錄之間,

也可能是第乙個索引記錄之前或最後乙個索引之後的空間。

最近使用者反饋說系統老是出現insert時,等待超時了,最後發現是insert間隙鎖!

間隙鎖是innodb中行鎖的一種, 但是這種鎖鎖住的卻不止一行資料,

他鎖住的是多行,是乙個資料範圍。間隙鎖的主要作用是為了防止出現幻讀,

但是它會把鎖定範圍擴大,

有時候也會給我們帶來麻煩,我們就遇到了。 

在資料庫引數中, 控制間隙鎖的引數是:innodb_locks_unsafe_for_binlog,

這個引數預設值是off, 也就是啟用間隙鎖, 他是乙個bool值, 當值為true時表示disable間隙鎖。

那為了防止間隙鎖是不是直接將innodb_locaks_unsafe_for_binlog設定為true就可以了呢? 

不一定!

而且這個引數會影響到主從複製及災難恢復, 這個方法還尚待商量。

間隙鎖的出現主要集中在同乙個事務中先delete後 insert

的情況下, 

當我們通過乙個引數去刪除一條記錄的時候, 

如果引數在資料庫中存在,

那麼這個時候產生的是普通行鎖,鎖住這個記錄, 然後刪除, 然後釋放鎖。

如果這條記錄不存在,

問題就來了, 資料庫會掃瞄索引,發現這個記錄不存在, 

這個時候的delete語句獲取到的就是乙個間隙鎖,

然後資料庫會向左掃瞄掃到第乙個比給定引數小的值,

向右掃瞄掃瞄到第乙個比給定引數大的值, 然後以此為界,

構建乙個區間, 

鎖住整個區間內的資料, 乙個特別容易出現死鎖的間隙鎖誕生了。

舉個例子:

表testlock,有兩個屬性id,和name.有如下資料。

開啟乙個會話: session 1

sql> set autocommit=0;##取消自動提交

sql> delete from testlock where id =

『6』;

在開啟乙個會話: session 2

sql> set autocommit=0;##取消自動提交

sql> insert into testlock(id,name) values(『6』,』hahaha』);

在沒有併發,或是極少併發的情況下, 這樣會可能會正常執行,在mysql中, 事務最終都是穿行執行,

但是在高併發的情況下, 

執行的順序就極有可能發生改變, 變成下面這個樣子:

sql> delete from testlock where id = 『6』;

sql> insert into testlock(id,name) values(『6』, 『hahaha』);

這個時候最後一條語句:insert into testlock(id,name) values(『6』, 『hahaha』); 執行時就會爆出死鎖錯誤。因為刪除id = 6這條記錄的時候,

id為6之後的部分都被鎖住了, 他們都取得了這乙個資料段的共享鎖, 所以在獲取這個資料段的排它鎖時出現死鎖。

這種問題的解決辦法:前面說了, 通過修改資料庫的引數innodb_locaks_unsafe_for_binlog來取消間隙鎖從而達到避免

這種情況的死鎖的方式尚待商量, 那就只有修改**邏輯, 存在才刪除,盡量不去刪除不存在的記錄。

mysql間隙鎖 mysql間隙鎖

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

mysql 間隙鎖 mysql間隙鎖 轉

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

mysql間隙鎖 mysql的間隙鎖

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