當我們用範圍條件而不是相等條件檢索資料,並請求共享或排他鎖時,innodb會給符合條件的已有資料記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做「間隙(gap)」,innodb也會對這個「間隙」加鎖,這種鎖機制就是所謂的間隙鎖(next-key鎖)。 舉例來說,假如emp表中只有101條記錄,其empid的值分別是 1,2,...,100,101,下面的sql:
select * from emp where empid > 100 for update;
複製**
是乙個範圍條件的檢索,innodb不僅會對符合條件的empid值為101的記錄加鎖,也會對empid大於101(這些記錄並不存在)的「間隙」加鎖。
innodb使用間隙鎖的目的,一方面是為了防止幻讀,以滿足相關隔離級別的要求,對於上面的例子,要是不使用間隙鎖,如果其他事務插入了empid大於100的任何記錄,那麼本事務如果再次執行上述語句,就會發生幻讀;另外一方面,是為了滿足其恢復和複製的需要。有關其恢復和複製對鎖機制的影響,以及不同隔離級別下innodb使用間隙鎖的情況,在後續的章節中會做進一步介紹。
很顯然,在使用範圍條件檢索並鎖定記錄時,innodb這種加鎖機制會阻塞符合條件範圍內鍵值的併發插入,這往往會造成嚴重的鎖等待。因此,在實際應用開發中,尤其是併發插入比較多的應用,我們要盡量優化業務邏輯,盡量使用相等條件來訪問更新資料,避免使用範圍條件。
還要特別說明的是,innodb除了通過範圍條件加鎖時使用間隙鎖外,如果使用相等條件請求給乙個不存在的記錄加鎖,innodb也會使用間隙鎖!
例子:假如emp表中只有101條記錄,其empid的值分別是1,2,......,100,101。
innodb儲存引擎的間隙鎖阻塞例子
session_1
session_2
mysql> select @@tx_isolation;
mysql> select @@tx_isolation;
+-----------------+
+-----------------+
@@tx_isolation
@@tx_isolation
+-----------------+
+-----------------+
repeatable-read
repeatable-read
+-----------------+
+-----------------+
1 row in set (0.00 sec)
1 row in set (0.00 sec)
mysql> set autocommit = 0;
mysql> set autocommit = 0;
query ok, 0 rows affected (0.00 sec)
query ok, 0 rows affected (0.00 sec)
當前session對不存在的記錄加for update的鎖:
mysql> select * from emp where empid = 102 for update;
empty set (0.00 sec)
這時,如果其他session插入empid為201的記錄(注意:這條記錄並不存在),也會出現鎖等待:
mysql>insert into emp(empid,...) values(201,...);
阻塞等待
session_1 執行rollback:
mysql> rollback;
query ok, 0 rows affected (13.04 sec)
由於其他session_1回退後釋放了next-key鎖,當前session可以獲得鎖並成功插入記錄:
mysql>insert into emp(empid,...) values(201,...);
query ok, 1 row affected (13.35 sec)
危害(坑):若執行的條件是範圍過大,則innodb會將整個範圍內所有的索引鍵值全部鎖定,很容易對效能造成影響。
mysql鎖 innodb間隙鎖死鎖分析
前言 在上篇裡分析了一次mysql死鎖問題,後來又深入研究了下死鎖的其他場景,innodb間隙鎖場景下也可能會發生死鎖,所以進一步鞏固下間隙鎖的知識 gap鎖定義 1.gap就是索引樹中插入新記錄的空隙 2.相應的gap鎖就是加在gap上的鎖 gap鎖作用 防止幻讀,通過間隙鎖阻止特定條件的新記錄的...
mysql間隙鎖導致死鎖
間隙鎖的分析 表結構如下 create table test gap id int 11 not null,主鍵 name varchar 255 not null,非唯一索引 primary key id key name name engine innodb default charset ut...
mysql間隙鎖 mysql的間隙鎖
最近學習了mysql的各種鎖,有點暈,打算通過文章的方式捋一捋。在學習了mvcc後,我就想,他已經很好的解決了併發讀寫了,但我也知道innodb提供了多種型別的鎖,所以很好奇這些鎖有什麼用,為什麼這些鎖的功能是mvcc做不到的?本文討論的都是rr級別下的鎖 我先建立乙個表,並插入幾行資料,如下圖 插...