MySQL 數(shù)據(jù)庫(kù)鎖:Record Lock, Gap Lock 和 Next-Key Lock
InnoDB引擎 在 共享鎖和排他鎖 文章中,我們?cè)敿?xì)分析了共享鎖和排他鎖在MySQL中是如何工作的,今天,我們接著分析InnoDB引擎的三種行鎖。
在MySQL的InnoDB引擎的行鎖主要有三類(lèi):
- Record Lock:記錄鎖,是在索引記錄上加鎖;
- Gap Lock:間隙鎖,鎖定一個(gè)范圍,但不包含記錄;
- Next-key Lock:Next-key Lock = Gap Lock + Record Lock,它鎖定了一個(gè)范圍(Gap Lock實(shí)現(xiàn)),并且鎖定記錄本身(Record Lock實(shí)現(xiàn));

一、Record Lock
1. 什么是 Record Lock?
Record Lock,記錄鎖,它是針對(duì)索引記錄的鎖,鎖定的總是索引記錄。在多用戶數(shù)據(jù)庫(kù)系統(tǒng)中,多個(gè)事務(wù)可能會(huì)同時(shí)嘗試讀取或修改同一條記錄,Record Lock確保只有一個(gè)事務(wù)能在某一時(shí)刻修改該記錄,其他事務(wù)只能讀取,或者在寫(xiě)鎖釋放后再進(jìn)行修改。
2. 舉例說(shuō)明
為了更好的說(shuō)明Record Lock,我們以下面的順序執(zhí)行流來(lái)進(jìn)行驗(yàn)證:
加鎖線程 sessionA | 線程B sessionB | 線程B sessionC |
#開(kāi)啟事務(wù) | ||
給user表id=1加寫(xiě)鎖 | ||
update user set | ||
查看 | ||
commit提交事務(wù) | ||
被堵塞的update操作執(zhí)行ok |
示例執(zhí)行結(jié)果如下圖:

通過(guò)上面的示例可以看出:
- 事務(wù)A(sessionA)對(duì)id=1加排他鎖之后產(chǎn)生了記錄鎖
- 事務(wù)B(sessionB)對(duì)id=1的update操作被阻塞了
- 事務(wù)C(sessionC)可以查看到Record Lock
二、Gap Lock
1. 什么是Gap Lock?
Gap Lock,間隙鎖,它是一種行級(jí)鎖,鎖住兩個(gè)索引記錄之間的間隙,而不是實(shí)際的數(shù)據(jù)記錄,由InnoDB隱式添加。
如下圖:(1,3) 表示鎖住記錄1 和記錄3 之間的間隙,這樣記錄2 就無(wú)法插入,間隙可能跨越單個(gè)索引值、多個(gè)索引值,甚至是空。

在InnoDB中,間隙鎖是通過(guò)索引來(lái)實(shí)現(xiàn)的。這意味著間隙鎖只能作用于索引,而不能直接作用于非索引列。當(dāng)一個(gè)事務(wù)對(duì)某個(gè)索引列上的間隙加鎖時(shí),其他事務(wù)就無(wú)法在這個(gè)間隙中插入新的記錄。
2. 舉例說(shuō)明
為了更好的說(shuō)明Gap Lock間隙鎖,我們以下面的順序執(zhí)行流來(lái)進(jìn)行驗(yàn)證:
加鎖線程 sessionA | 線程B sessionB | 線程C sessionC |
#開(kāi)啟事務(wù) | ||
加鎖 | ||
insert into user(id,age) values(2,20); | ||
#查看 | ||
commit提交事務(wù) | ||
# 被堵塞的 |
示例執(zhí)行結(jié)果如下圖:

通過(guò)上面的示例執(zhí)行結(jié)果可以看出:
- 事務(wù)A(sessionA)在加共享鎖的時(shí)候產(chǎn)生了間隙鎖(Gap Lock)
- 事務(wù)B(sessionB)對(duì)間隙中進(jìn)行insert/update操作,需要先獲取排他鎖(X),導(dǎo)致阻塞
- 事務(wù)C(sessionC)通過(guò)show engine innodb status\G指令可以查看到間隙鎖的存在。
需要說(shuō)明,間隙鎖只是鎖住間隙內(nèi)部的范圍,在間隙外的insert/update操作不會(huì)受影響。
三、Next-Key Lock
1. 什么是Next-Key Lock?
Next-Key Lock,稱(chēng)為臨鍵鎖,它是Record Lock + Gap Lock的組合,用來(lái)鎖定一個(gè)范圍,并且鎖定記錄本身鎖,它是一種左開(kāi)右閉的范圍,可以用符號(hào)表示為:(a,b]。如下圖:

2. 舉例說(shuō)明
為了更好的說(shuō)明Next-Key Lock,我們以下面的順序執(zhí)行流來(lái)進(jìn)行驗(yàn)證:
加鎖線程 sessionA | 線程B sessionB | 線程C sessionC | 線程D sessionD |
#開(kāi)啟事務(wù) | |||
#加鎖 | |||
#獲取鎖失敗 | |||
#update被堵塞 | #查看 | ||
提交事務(wù)Gap Lock被釋放 | |||
被堵塞的insert操作執(zhí)行ok | #被堵塞的update操作執(zhí)行成功 |
示例執(zhí)行結(jié)果如下圖:

通過(guò)上面的示例執(zhí)行結(jié)果可以看出:
- 事務(wù)A(sessionA)在加共享鎖的時(shí)候產(chǎn)生了間隙鎖(Gap Lock)
- 事務(wù)B(sessionB)對(duì)間隙中進(jìn)行insert操作,需要先獲取排他鎖(X),導(dǎo)致阻塞。
- 事務(wù)C(sessionC)對(duì)間隙中進(jìn)行update操作,需要先獲取排他鎖(X),導(dǎo)致阻塞。
- 事務(wù)D(sessionD)通過(guò)show engine innodb status\G指令可以查看到間隙鎖的存在。需要說(shuō)明的,間隙鎖只是鎖住間隙內(nèi)部的范圍,在間隙外的insert/update操作不會(huì)受影響。
四、總結(jié)
Record Lock,Gap Lock和Gap Lock 3種鎖是存在MySQL的InnoDB引擎的行鎖,MyISAM引擎沒(méi)有:
- Record Lock:記錄鎖,是在索引記錄上加鎖;
- Gap Lock:間隙鎖,鎖定一個(gè)范圍,但不包含記錄,即(A,B);
- Next-key Lock:Next-key Lock = Gap Lock + Record Lock,它鎖定了一個(gè)范圍(Gap Lock實(shí)現(xiàn)),并且鎖定記錄本身(Record Lock實(shí)現(xiàn)),即(A,B];;
這 3種鎖都是InnoDB引擎隱式添加的,目的是為了解決可重復(fù)讀隔離級(jí)別下幻讀的現(xiàn)象。




























