首先mysql引入間隙鎖是為了解決幻讀的問題。間隙鎖之間並不產生衝突,但間隙鎖與插入資料之間會產生衝突。間隙鎖的引入,可能會導致同樣的語句鎖住更大的範圍,影響併發度。mysql加鎖的規則十分複雜並且隨著版本更新進行變動,整體的加鎖規則如下,包含了兩個「原則」、兩個「優化」和乙個「bug」(所有都是在可重複讀的隔離級別)
原則1:加鎖的基本單位是next-key lock,next-key lock是前開後閉區間。
原則2:查詢過程中訪問到的物件才會加鎖。
優化1:索引上的等值查詢,給唯一索引加鎖的時候,next-key lock退化為行鎖。
優化2:索引上的等值查詢,向右遍歷時且最後乙個值不滿足等值條件的時候,next-key lock退化為間隙鎖。
乙個bug:唯一索引上的範圍查詢會訪問到不滿足條件的第乙個值為止。
下面以這個表為例:
案例一:事務a事務b事務c
begin;update t set d = d+1 where id = 7
insert into t values(8,8,8);
(blocked)
update t set d = d+1 where id = 10;
分析:首先事務a,進行update,where使用的是主鍵索引,加鎖應該加(5,10],然後發現是唯一索引,且是等值查詢,所以根據優化2向右遍歷,到第乙個不滿足的10,所以加鎖為(5,10);
事務b插入資料在間隙鎖之間,所以blocked;
事務c成功執行;
案例二:
事務a事務b事務c
begin;select id from t where c=5 lock in share mode;
update t set d = d+1 where id = 5;
(blocked)
insert into t values(7,7,7);
(blocked)
分析:首先事務a使用普通索引c,且為覆蓋索引,應該鎖(0,5],(5,10],根據優化2,變成(0,5],(5,10),但是由於是lock in share mode
只鎖覆蓋索引,所以主鍵索引並沒有用到,所以也沒有加鎖。但是如果是執行for update
時系統會認為你接下來要更新資料,因此會順便給主鍵索引上滿足條件的行加上行鎖。
事務b使用主鍵索引,所以正常更新
事務c插入資料時收到間隙鎖的限制,被鎖。
案例三
事務a事務b事務c
begin;select * from t where id>=10 and id<11 for update;
insert into t values(8,8,8);
(ok)insert into t values(13,13,13);
(blocked)
update t set d = d+1 where id = 15;
(blocked)
分析:事務a採用主鍵索引,應該加上間隙鎖(5,10],(10,15],由於存在10這一行,根據優化1,等值查詢,所以變為10這一行行鎖+(10,15]。
事務b第一條語句成功,第二條語句被間隙鎖鎖住
事務c被間隙鎖鎖住。
案例四
事務a事務b事務c
begin;select * from t where c>=10 and c<11 for update;
insert into t values(8,8,8);
(blocked)
update t set d = d+1 where c=15;
(blocked)
分析:事務a在c上不是唯一索引,所以鎖住(5,10],(10,15]
事務b被鎖
事務c被鎖
注意:在刪除資料的時候盡量加limit。這樣不僅可以控制刪除資料的條數,讓操作更安全,還可以減小加鎖的範圍
mysql實戰45講
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級別下的鎖 我先建立乙個表,並插入幾行資料,如下圖 插...