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

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

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

1. 行鎖(Record Lock)

定義

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

作用

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

觸發(fā)場景

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

例子

假設有表:

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

事務 A:

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

會被阻塞,直到事務 A 提交或回滾。

2. 間隙鎖(Gap Lock)

定義

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

作用

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

觸發(fā)場景

  • 范圍查詢并加鎖時(FOR UPDATE 或 LOCK IN SHARE MODE)。
  • 在 REPEATABLE READ 下,InnoDB 會自動加 Gap Lock 來防止幻讀。

例子

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

id: 1, 5, 10

事務 A:

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

會被阻塞,因為 (5,10) 的間隙被鎖住。

3. 區(qū)別總結

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

? 總結

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

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

是的,

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

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

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

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

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

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

如果執(zhí)行:

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

InnoDB 會:

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

2. 如果 a 和 b 很遠

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

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

3. 注意事項

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

4. 直觀示意

假設:

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 之間范圍特別大,可以考慮:

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

為什么5前面沒有被鎖住?

在執(zhí)行

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

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

核心原因:鎖定范圍是由查詢條件決定的

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

  • 查詢條件是 id BETWEEN 5 AND 50
  • 范圍的起點是 id=5
  • 所以它不會去鎖 (1,5) 這個間隙,因為這個間隙里的值(比如 2、3、4)不滿足條件,不會影響當前事務的結果集。

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

REPEATABLE READ 隔離級別下:

  1. Record Lock:鎖住滿足條件的記錄(這里是 id=5, 10, 20, 50)。
  2. Gap Lock:鎖住這些記錄之間的間隙,以及最后一條記錄到下一條記錄之間的間隙。
  3. 不鎖條件范圍外的間隙,因為它們不會導致幻讀。

例子對比

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

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

查詢:

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) 不鎖,因為不在條件范圍內(nèi)。

如果是:

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

鎖定范圍:

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

  • 依然不會鎖 (1,5),因為條件是 >=5

如果是:

SELECT * FROM user WHERE id > 1 FOR UPDATE;

鎖定范圍:

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

  • 這時 (1,5) 會被鎖,因為它在條件范圍內(nèi)(>1)。

? 總結

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

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

相關文章

最新評論

台前县| 保靖县| 长泰县| 溧水县| 巫山县| 岳西县| 宜城市| 陆河县| 灯塔市| 安顺市| 龙里县| 绍兴县| 册亨县| 鄂尔多斯市| 长子县| 定安县| 四川省| 仁化县| 南乐县| 中方县| 满洲里市| 彭州市| 江北区| 宁明县| 长丰县| 老河口市| 佛教| 寿阳县| 刚察县| 兴化市| 晋中市| 宁陕县| 棋牌| 叙永县| 东明县| 三门峡市| 澄城县| 宕昌县| 灵武市| 贡觉县| 屏南县|