当前位置: 首页 > news >正文

Mysql--基础知识点--98--临键锁 VS 间隙锁

在 MySQL InnoDB 中,临键锁间隙锁都是用于解决幻读(在 RR 隔离级别下)的锁机制,但它们的作用范围不同:

  • 间隙锁(Gap Lock):只锁定索引记录之间的“间隙”,不锁定记录本身
  • 临键锁(Next-Key Lock):是行锁 + 间隙锁的组合,锁定一个记录及其前面的间隙(左开右闭区间)。

主要区别

维度间隙锁临键锁
锁定范围仅间隙(记录之间的空间)记录本身 + 该记录前面的间隙
是否锁定记录❌ 否✅ 是
典型产生场景查询条件使用范围但命中不存在的记录默认的索引扫描/范围查询(RR隔离级别)
目的防止幻读(阻止其他事务在间隙中插入新记录)防止幻读 + 保护已有记录

举例说明

假设有一个表tid是主键,现有记录:1, 3, 5
(当前事务隔离级别为REPEATABLE READ

1. 临键锁示例

-- 事务 ABEGIN;SELECT*FROMtWHEREid=3FORUPDATE;

InnoDB 会对id=3这条记录加上临键锁,锁定的区间为(1, 3](即从上一个记录1到当前记录3的区间,包含3本身)。

此时:

  • 事务 B 尝试INSERT INTO t VALUES (2);阻塞(因为(1,3)间隙被锁)
  • 事务 B 尝试INSERT INTO t VALUES (3);阻塞(记录3被锁)
  • 事务 B 尝试INSERT INTO t VALUES (4);不阻塞4属于间隙(3,5),未被锁)

2. 间隙锁示例

-- 事务 ABEGIN;SELECT*FROMtWHEREid=2FORUPDATE;-- id=2 不存在

因为id=2不存在,InnoDB 只对间隙(1, 3)加上间隙锁不会锁定任何记录(记录13本身未被锁)。

此时:

  • 事务 B 尝试INSERT INTO t VALUES (2);阻塞(在间隙(1,3)中插入)
  • 事务 B 尝试INSERT INTO t VALUES (1);不阻塞1是已存在记录,且未被锁;但若1不存在,插入1也不阻塞,因为间隙锁范围是(1,3),不包括1
  • 事务 B 尝试INSERT INTO t VALUES (3);不阻塞(记录3本身没有被锁)
  • 事务 B 尝试UPDATE t SET id = 3 WHERE id = 1;→ 可以执行(不影响间隙)

小结

  • 临键锁 = 行锁 + 间隙锁,锁定范围更广,用于保护现有记录及防止相邻间隙的幻读。
  • 间隙锁仅锁住“空白区域”,不影响已有记录的修改或删除,只阻止在间隙中插入新数据。

在实际使用中,InnoDB 默认采用临键锁;

  • 唯一索引
    • 等值查询:当命中唯一索引等值查询且记录存在时,临键锁会退化为行锁;当查询不存在的记录时,则会退化为间隙锁。
    • 范围查询: 看下边的问题范围查询时用的是行锁、临键锁、行锁 哪个?的答案
  • 非唯一索引
    • 等值查询: 当命中非唯一索引等值查询且记录存在时,还是间隙锁不会退化,原因看下边的问题当命中非唯一索引等值查询且记录存在时会加什么样的锁;当查询不存在的记录时,则会退化为间隙锁。
    • 范围查询:跟唯一索引差不多

问:范围查询时用的是行锁、临键锁、行锁 哪个?

在 MySQL InnoDB 的RR(可重复读)隔离级别下,范围查询默认使用的是临键锁(Next-Key Lock)
它本质上是“行锁 + 间隙锁”的组合,既锁定查询范围内的已有记录(行锁),也锁定这些记录之间的间隙(间隙锁),从而防止幻读。

不同情况的具体表现

场景RR 隔离级别RC 隔离级别
范围查询(如WHERE id > 10临键锁(锁定索引区间及间隙)行锁(仅锁定命中的记录,无间隙锁)
唯一索引等值查询(记录存在)行锁(临键锁退化为行锁)行锁
唯一索引等值查询(记录不存在)间隙锁无锁(或行锁?RC 下不加间隙锁,不会阻塞插入)

举例说明(RR 级别)

t(id PK)有记录:1, 3, 5, 7

-- 事务 ABEGIN;SELECT*FROMtWHEREid>3FORUPDATE;-- 范围查询

此时 InnoDB 会加临键锁,锁定的索引范围是:

  • id=3的下一条记录5开始,直到正无穷。
  • 具体会锁住(3,5](5,7](7, +∞)这些区间(包含记录本身和前面的间隙)。

影响

  • 其他事务无法在id > 3的范围内插入新记录(如插入468都会阻塞),也无法修改或删除57等已有记录。
  • 这保证了在事务 A 结束前,反复执行相同的范围查询,结果集始终不变(防止幻读)。

与 RC 的对比

如果隔离级别是RC(读已提交)

  • 范围查询只加行锁(仅锁住实际查到的记录57)。
  • 不会锁间隙,因此其他事务可以在间隙中插入新记录(如插入4),导致幻读。

总结

  • RR 隔离级别 + 范围查询→ 使用临键锁(行锁+间隙锁)
  • RC 隔离级别 + 范围查询→ 只使用行锁(无间隙锁,无临键锁)

所以,回答你的问题:范围查询在 InnoDB 中(RR 下)用的是临键锁


再问:在RR级别,那如果是 表 t(id PK) 有记录:1, 3, 5, 7。id>=3 呢,锁住的范围是什么?

RR(可重复读)隔离级别下,对id >= 3的范围查询使用FOR UPDATE加锁时,InnoDB 会使用**临键锁(Next-Key Lock)**锁定以下范围:

锁定的具体范围

表中有记录:1, 3, 5, 7
WHERE id >= 3会命中记录3, 5, 7

1. 对每个命中记录加临键锁(左开右闭区间)

  • 对于id = 3:临键锁区间为(1, 3]
  • 对于id = 5:临键锁区间为(3, 5]
  • 对于id = 7:临键锁区间为(5, 7]

2. 还需要锁定最大记录之后的间隙

  • 最后一个记录7之后的正无穷区间:(7, +∞)(也是一个间隙锁)

3. 综合结果

锁定的所有区间为:
(1, 3](3, 5](5, 7](7, +∞)=(1, +∞)

即:所有大于 1 的 id 值(包括记录和间隙)都被锁住

  • 记录被锁id = 3, 5, 7不能由其他事务修改或删除。
  • 间隙被锁:任何在(1, +∞)范围内的插入操作(如插入2, 4, 6, 8, 100)都会被阻塞。
  • 记录1不受影响:其他事务可以正常修改或删除id = 1的记录。

示例验证

其他事务的操作是否阻塞原因
INSERT INTO t VALUES (2);✅ 阻塞落在间隙(1,3)
INSERT INTO t VALUES (4);✅ 阻塞落在间隙(3,5)
INSERT INTO t VALUES (6);✅ 阻塞落在间隙(5,7)
INSERT INTO t VALUES (8);✅ 阻塞落在间隙(7, +∞)
UPDATE t SET id=... WHERE id=3;✅ 阻塞记录3被临键锁锁定
DELETE FROM t WHERE id=5;✅ 阻塞记录5被临键锁锁定
UPDATE t SET ... WHERE id=1;❌ 不阻塞记录1未被锁
INSERT INTO t VALUES (0);❌ 不阻塞落在(-∞,1]区间,未锁定

总结

  • id >= 3锁定的范围是id > 1的所有空间(即(1, +∞))。
  • 相当于从第一个命中记录的前一个间隙开始(不包括前一个记录本身),一直锁到正无穷。
  • 这是 InnoDB 在 RR 级别下为了防止幻读所采取的标准行为。

再问:当命中非唯一索引等值查询且记录存在时会加什么样的锁

RR(可重复读)隔离级别下,当命中非唯一索引等值查询且记录存在时(例如SELECT ... WHERE name = 'Alice' FOR UPDATEname为非唯一索引),InnoDB 会加临键锁(Next-Key Lock),而不会退化为行锁。

加锁的具体规则

1. 对辅助索引加临键锁

  • 对于找到的每条满足条件的辅助索引记录,InnoDB 会对其加上临键锁,锁定区间为(上一个不同索引值, 当前索引值]
  • 由于非唯一索引可能存在多条相同值的记录,InnoDB 会锁定所有相同值记录及其之间的间隙,并且还会锁定从最后一个相同值到下一个不同值之间的间隙(即右边界扩展到下一个不同值)。
  • 最终效果:锁住从上一个不同值到下一个不同值之间的整个区间(不包含左边界和右边界记录本身,但包含区间内的所有记录和间隙)。

2. 对聚集索引(主键)加行锁

  • 对于每个匹配的辅助索引记录对应的主键记录,InnoDB 也会加上行锁(Record Lock),防止其他事务通过主键直接修改或删除这些行。

举例说明

假设有一个表t

CREATETABLEt(idINTPRIMARYKEY,nameVARCHAR(10),INDEXidx_name(name));INSERTINTOtVALUES(1,'Alice'),(2,'Alice'),(3,'Bob'),(4,'Charlie');

RR 隔离级别下,事务 A 执行:

BEGIN;SELECT*FROMtWHEREname='Alice'FORUPDATE;

加锁情况

  • 辅助索引idx_name上的值分布:'Alice' (id=1),'Alice' (id=2),'Bob' (id=3),'Charlie' (id=4)
  • 上一个不同索引值:无(可以视为-∞
  • 当前索引值:'Alice'
  • 下一个不同索引值:'Bob'
  • InnoDB 会锁定(-∞, 'Alice']('Alice', 'Bob']两个临键锁区间?实际上,由于'Alice'有多条,它会锁定从-∞'Bob'之间的所有间隙和记录,具体是:
    • 临键锁1:(-∞, 'Alice'](包含第一个'Alice'及其前面的间隙)
    • 临键锁2:('Alice', 'Alice']?不,对于第二条'Alice',其前一条是第一条'Alice',所以临键锁是('Alice', 'Alice'],这个区间实际上只包含第二条'Alice'本身(因为两条相同的值之间没有间隙)。
    • 然后还会对'Alice''Bob'之间的间隙加锁:即临键锁('Alice', 'Bob'](包含'Bob'吗?不,临键锁是左开右闭,'Bob'本身属于这个锁,但'Bob'是下一个不同值,是否会被锁?实际上,这个临键锁会锁住'Bob'记录本身,但'Bob'不满足name='Alice',所以这个锁是必要的,以防止幻读?重要:根据 InnoDB 实现,范围查询会扫描到第一个不满足条件的记录,并对该记录也加临键锁。因此,对于等值查询name='Alice',InnoDB 会定位到第一条'Alice',然后继续扫描直到第一个不等于'Alice'的记录(即'Bob'),并对'Bob'也加上临键锁('Alice', 'Bob']。这样,其他事务无法在('Alice', 'Bob')间隙中插入新记录(如插入'Alice''Alice2'),也无法修改或删除'Bob'本身?实际上,'Bob'被锁住后,其他事务不能修改或删除id=3这一行,但这是否合理?这其实是 InnoDB 为了防止幻读的保守策略:因为如果允许修改'Bob''Alice',就会导致新'Alice'出现,影响当前查询结果。所以确实会锁住'Bob'

因此,最终的锁定范围是-∞'Bob'的所有间隙和记录(包含所有'Alice''Bob'记录)。这样,其他事务:

  • 无法插入name='Alice'的新记录(因为间隙被锁)
  • 无法插入name值在'Alice''Bob'之间的记录(如'Alice2',按字符串排序在'Alice''Bob'之间)
  • 无法修改'Bob'为其他值,也无法修改'Alice'记录
  • 无法删除'Alice''Bob'记录

对比唯一索引等值查询(记录存在):

  • 唯一索引不需要锁定下一个不同值,因为唯一性保证了不会有新记录插入相同值,且修改其他值不影响等值查询。所以退化为行锁。

总结

索引类型等值查询记录存在RR级别下加的锁
唯一索引(含主键)行锁(退化为 Record Lock)
非唯一索引临键锁(Next-Key Lock,锁定一个区间,包含间隙和记录)

因此,回答你的问题:非唯一索引等值查询且记录存在时,加的是临键锁(并且还会对对应的主键记录加行锁)。

http://www.jsqmd.com/news/642357/

相关文章:

  • 除螨仪到底有没有效果?2026 十款家用高性价比除螨仪品牌精选推荐
  • LightGBM核心优化策略与实战调参指南
  • 2026年普通人做什么副业真能赚钱?1w个样本告诉你答案
  • spring ai如何实现Agent工作流编排,支持多轮对话,上下文记忆,工具自动调用?
  • 保姆级教程:PVE/Proxmox VE拔掉独显后网络失联?一招搞定网卡名绑定(Debian系通用)
  • **发散创新:基于Python的文件API深度封装与实战应用**在现代软件开发中,**文
  • ubuntu的lazarus的Tline/TeaLine组件的构思
  • KEBA DI325数字输入模块卡
  • Kafka 的 ISR 是什么
  • 团队任务管理软件哪个好?trello、Worktile、Todoist等10大产品对比
  • 提高文本表达清晰度指令
  • 3步终极解锁:中兴光猫工厂模式与Telnet服务完全指南
  • ESP32驱动1.8寸TFT屏幕(ST7735)避坑指南:从User_Setup.h配置到显示时钟的完整流程
  • **发散创新:基于Go语言的协同计算框架设计与实践**在现代分布式系统中,**协同计算(Collaborative
  • 记忆的遗忘与压缩:Harness 的上下文维护
  • 如何5分钟快速上手抖音批量下载神器:douyin-downloader完整指南
  • 安庆口碑好的健身房有哪些
  • 身份证OCR识别系统完整搭建指南
  • 高速纸机脱水元件,为何氧化锆成首选
  • 3个理由告诉你为什么League Akari是英雄联盟玩家的必备智能助手
  • pytest自动化测试框架从0到1实战
  • 互联网大厂Java面试全场景技术栈解析与模拟问答
  • HarmonyOS StateStore 全局状态管理实战
  • 终极指南:如何免费解锁Cursor AI编辑器的完整Pro功能
  • Oracle监听程序配置全攻略:从ORA-12541错误到完美解决(附PLSQL连接技巧)
  • 双叶家具联系方式查询:在山西大同选购实木家具时如何通过官方渠道联系与实地探访 - 品牌推荐
  • **发散创新:基于 OpenTelemetry 的分布式链路追踪实战与性能
  • 网盘直链下载助手:八大网盘一键解析,告别限速烦恼的终极解决方案
  • 无线充电电动牙刷设计解析:瑞萨R7F0C807与PWM驱动技术
  • 性能测试项目中遇到的20个问题以及解决方法