最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL?中的行鎖(Record?Lock)?和?間隙鎖(Gap?Lock)詳解

 更新時(shí)間:2025年11月01日 10:54:37   作者:大G的筆記本  
InnoDB中的行鎖(RecordLock)和間隙鎖(GapLock)是用于保證事務(wù)隔離性的兩種鎖機(jī)制,本文給大家介紹MySQL中的行鎖(Record?Lock)?和間隙鎖(Gap?Lock),感興趣的朋友跟隨小編一起看看吧

1. 行鎖(Record Lock)

定義

  • Record Lock 是 InnoDB 在事務(wù)中對(duì)索引記錄加的鎖,用于保護(hù)某一行數(shù)據(jù)不被其他事務(wù)修改。
  • 它是基于索引的鎖,如果沒(méi)有索引,InnoDB 會(huì)退化為表鎖。

作用

  • 防止其他事務(wù)修改或刪除當(dāng)前事務(wù)正在處理的行。
  • 保證事務(wù)的隔離性(尤其是 REPEATABLE READ 和 SERIALIZABLE 隔離級(jí)別)。

觸發(fā)場(chǎng)景

  • 常見(jiàn)于 SELECT ... FOR UPDATE 或 UPDATE、DELETE 操作。
  • 必須通過(guò)索引定位行,否則會(huì)鎖住更多數(shù)據(jù)(甚至全表)。

例子

假設(shè)有表:

CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(50), age INT ) ENGINE=InnoDB;

事務(wù) A:

BEGIN; SELECT * FROM user WHERE id=5 FOR UPDATE;
  • InnoDB 會(huì)在 id=5 這一行的索引記錄上加 Record Lock
  • 事務(wù) B 如果執(zhí)行:
UPDATE user SET age=30 WHERE id=5;

會(huì)被阻塞,直到事務(wù) A 提交或回滾。

2. 間隙鎖(Gap Lock)

定義

  • Gap Lock 是 InnoDB 在事務(wù)中對(duì)索引記錄之間的間隙加的鎖。
  • 它鎖住的是索引之間的空隙,而不是具體的行。
  • 主要用于防止幻讀(Phantom Read)。

作用

  • 阻止其他事務(wù)在某個(gè)索引范圍內(nèi)插入新記錄。
  • 常見(jiàn)于范圍查詢(xún)(BETWEEN>、<)或 REPEATABLE READ 隔離級(jí)別下的 SELECT ... FOR UPDATE。

觸發(fā)場(chǎng)景

  • 范圍查詢(xún)并加鎖時(shí)(FOR UPDATE 或 LOCK IN SHARE MODE)。
  • 在 REPEATABLE READ 下,InnoDB 會(huì)自動(dòng)加 Gap Lock 來(lái)防止幻讀。

例子

假設(shè)表中有數(shù)據(jù):

id: 1, 5, 10

事務(wù) A:

BEGIN; SELECT * FROM user WHERE id BETWEEN 5 AND 10 FOR UPDATE;
  • InnoDB 會(huì)對(duì) id=5 和 id=10 加 Record Lock。
  • 同時(shí)會(huì)對(duì) (5,10) 之間的空隙加 Gap Lock。
  • 事務(wù) B 如果執(zhí)行:
INSERT INTO user VALUES (7, 'Tom', 25);

會(huì)被阻塞,因?yàn)?(5,10) 的間隙被鎖住。

3. 區(qū)別總結(jié)

鎖類(lèi)型鎖住對(duì)象作用常見(jiàn)場(chǎng)景
Record Lock某一行的索引記錄防止該行被修改或刪除精確匹配索引的 UPDATE、DELETE、SELECT ... FOR UPDATE
Gap Lock索引記錄之間的空隙防止在范圍內(nèi)插入新記錄范圍查詢(xún)加鎖,防止幻讀

? 總結(jié)

  • Record Lock:鎖住已有的行,防止修改或刪除。
  • Gap Lock:鎖住索引間的空隙,防止插入新行。
  • 兩者經(jīng)常一起出現(xiàn),比如范圍查詢(xún)時(shí)會(huì)同時(shí)鎖住已有行和間隙,這種組合鎖叫 Next-Key Lock。
BEGIN;
SELECT * FROM user WHERE id BETWEEN a AND b FOR UPDATE;

如果a和b距離很大是否直接鎖住a和b中間所有行

是的,

在 InnoDB 的 REPEATABLE READ 隔離級(jí)別下,執(zhí)行

BEGIN; SELECT * FROM user WHERE id BETWEEN a AND b FOR UPDATE;

會(huì)觸發(fā) Next-Key LockRecord Lock + Gap Lock 的組合),它會(huì)鎖住范圍內(nèi)所有匹配的行,并且鎖住這些行之間的間隙,防止其他事務(wù)在這個(gè)范圍內(nèi)插入新數(shù)據(jù)。

1. 鎖定范圍的規(guī)則

假設(shè) id 是主鍵索引,表中數(shù)據(jù)如下:

id: 1, 5, 10, 20, 50, 100

如果執(zhí)行:

SELECT * FROM user WHERE id BETWEEN 5 AND 50 FOR UPDATE;

InnoDB 會(huì):

  • 對(duì) id=5、id=10、id=20、id=50 加 Record Lock(行鎖)
  • 對(duì) (5,10)、(10,20)、(20,50) 這些間隙加 Gap Lock
  • 還會(huì)對(duì) (50, 下一條記錄) 的間隙加鎖(防止插入 51、60 等)

2. 如果 a 和 b 很遠(yuǎn)

如果 a=5,b=1000000,而表中有很多行:

  • 是的,InnoDB 會(huì)鎖住 id=5 到 id=1000000 范圍內(nèi)所有匹配的行它們之間的間隙。
  • 這意味著這個(gè)范圍內(nèi)的更新、刪除、插入都會(huì)被阻塞,直到事務(wù)提交或回滾。
  • 如果范圍特別大,可能會(huì)造成大范圍鎖定,嚴(yán)重影響并發(fā)性能。

3. 注意事項(xiàng)

  • 基于索引:行鎖和間隙鎖都是基于索引的,如果 id 沒(méi)有索引,InnoDB 會(huì)退化成表鎖,鎖住整張表。
  • 范圍越大,鎖的行和間隙越多,并發(fā)沖突風(fēng)險(xiǎn)越高。
  • 如果只想鎖住已存在的行而不鎖間隙,可以使用 READ COMMITTED 隔離級(jí)別(Gap Lock 不會(huì)生效)。

4. 直觀示意

假設(shè):

id: 1, 5, 10, 20, 50, 100

執(zhí)行:

SELECT * FROM user WHERE id BETWEEN 5 AND 50 FOR UPDATE;

鎖定范圍:

[5]====(gap)====[10]====(gap)====[20]====(gap)====[50]====(gap)====

  • [x] 表示 Record Lock(行鎖)
  • (gap) 表示 Gap Lock(間隙鎖)

我建議,如果你的 ab 之間范圍特別大,可以考慮:

  • 拆分查詢(xún),減少一次性鎖定的范圍
  • 使用更精確的條件,避免鎖住無(wú)關(guān)數(shù)據(jù)
  • 降低隔離級(jí)別(如 READ COMMITTED)減少 Gap Lock

為什么5前面沒(méi)有被鎖???

在執(zhí)行

BEGIN; SELECT * FROM user WHERE id BETWEEN 5 AND 50 FOR UPDATE;

的時(shí)候,為什么 id=5 前面的間隙(比如 (1,5))沒(méi)有被鎖住?

核心原因:鎖定范圍是由查詢(xún)條件決定的

InnoDB 的 Next-Key Lock(行鎖 + 間隙鎖)只會(huì)鎖住滿(mǎn)足查詢(xún)條件的記錄以及這些記錄之間的間隙。

  • 查詢(xún)條件是 id BETWEEN 5 AND 50
  • 范圍的起點(diǎn)是 id=5
  • 所以它不會(huì)去鎖 (1,5) 這個(gè)間隙,因?yàn)檫@個(gè)間隙里的值(比如 2、3、4)不滿(mǎn)足條件,不會(huì)影響當(dāng)前事務(wù)的結(jié)果集。

鎖定范圍的精確規(guī)則

REPEATABLE READ 隔離級(jí)別下:

  1. Record Lock:鎖住滿(mǎn)足條件的記錄(這里是 id=5, 10, 20, 50)。
  2. Gap Lock:鎖住這些記錄之間的間隙,以及最后一條記錄到下一條記錄之間的間隙。
  3. 不鎖條件范圍外的間隙,因?yàn)樗鼈儾粫?huì)導(dǎo)致幻讀。

例子對(duì)比

假設(shè)表數(shù)據(jù):

id: 1, 5, 10, 20, 50, 100

查詢(xún):

SELECT * FROM user WHERE id BETWEEN 5 AND 50 FOR UPDATE;

鎖定范圍:

[5]====(gap)====[10]====(gap)====[20]====(gap)====[50]====(gap)====

  • [x] = Record Lock
  • (gap) = Gap Lock
  • (1,5) 不鎖,因?yàn)椴辉跅l件范圍內(nèi)。

如果是:

SELECT * FROM user WHERE id >= 5 FOR UPDATE;

鎖定范圍:

[5]====(gap)====[10]====(gap)====[20]====(gap)====[50]====(gap)====[100]====(gap)====

  • 依然不會(huì)鎖 (1,5),因?yàn)闂l件是 >=5。

如果是:

SELECT * FROM user WHERE id > 1 FOR UPDATE;

鎖定范圍:

(1,5)====[5]====(gap)====[10]====(gap)====[20]====(gap)====[50]====(gap)====[100]====(gap)====

  • 這時(shí) (1,5) 會(huì)被鎖,因?yàn)樗跅l件范圍內(nèi)(>1)。

? 總結(jié)

  • InnoDB 只鎖條件范圍內(nèi)的記錄和間隙,不會(huì)鎖條件范圍外的間隙。
  • BETWEEN 5 AND 50 的起點(diǎn)是 5,所以 5 前面的間隙不會(huì)被鎖。
  • 如果條件包含更小的值(比如 >1),那么 5 前面的間隙就會(huì)被鎖。

到此這篇關(guān)于MySQL 中的行鎖(Record Lock) 和 間隙鎖(Gap Lock)詳解的文章就介紹到這了,更多相關(guān)mysql行鎖和間隙鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

大同市| 吉安市| 滨州市| 农安县| 平陆县| 尼木县| 明溪县| 中宁县| 枝江市| 融水| 崇左市| 乐安县| 鄂温| 湾仔区| 绥滨县| 绥阳县| 灵武市| 新乡县| 高平市| 蒙阴县| 大足县| 长白| 和平区| 朝阳市| 松滋市| 铜川市| 龙江县| 嵊泗县| 霞浦县| 栾川县| 永州市| 合川市| 临夏县| 邯郸市| 井陉县| 南溪县| 连平县| 通道| 体育| 济南市| 新野县|