游乐游手机版
首页/数据库/文章详情

MySQL记录锁与间隙锁的区别及应用场景

时间:2026-08-17 07:06
记录锁只会锁住已经存在的索引记录,间隙锁则用于锁定两个索引值之间的空白区间以阻止新数据插入;当使用非唯一索引进行等值查询时,二者通常会组合成临键锁。要准确判断 MySQL InnoDB 当前使用的是哪种锁,需要通过SHOW ENGINE INNODB STATUS确认,而且具体加锁方式还会受到事务隔

记录锁只会锁住已经存在的索引记录,间隙锁则用于锁定两个索引值之间的空白区间以阻止新数据插入;当使用非唯一索引进行等值查询时,二者通常会组合成临键锁。要准确判断 MySQL InnoDB 当前使用的是哪种锁,需要通过SHOW ENGINE INNODB STATUS确认,而且具体加锁方式还会受到事务隔离级别与索引类型的共同影响。

MySQL的记录锁与间隙锁有什么区别?

记录锁只锁已存在的索引行,不会锁定索引间隙

记录锁(Record Lock)是 InnoDB 中真正意义上“锁某一行”的最小粒度锁,但它锁住的并不是物理数据行本身,而是该行在**聚簇索引或二级索引中的对应索引记录**。只要 SQL 条件能够命中索引,尤其是主键索引或唯一索引,并且精确匹配到某条已存在的数据,InnoDB 通常只会加记录锁。

常见触发场景:

  • SELECT * FROM users WHERE id = 10 FOR UPDATE; —— id 是主键,命中后只锁该条索引记录
  • UPDATE orders SET status = 'paid' WHERE order_no = 'ORD-2026-001'; —— order_no 是唯一索引,也只会锁对应记录

关键点:如果没有走索引,MySQL InnoDB 的加锁范围可能显著扩大;如果查询没有找到目标记录,也不会产生记录锁——此时更有可能出现的是间隙锁。

间隙锁只锁“空白区间”,核心作用是防止插入新数据

间隙锁(Gap Lock)不会锁住任何真实存在的数据行,它锁定的是**两个索引值之间的空隙范围**,通常可以表示为左开右开的区间,例如 (10, 20)。它的主要目的只有一个:阻止其他事务在这个索引区间内执行 INSERT,从而避免幻读问题。

典型触发条件:

  • 事务隔离级别通常需要是 REPEATABLE READ(在 READ COMMITTED 下默认不会启用大多数间隙锁)
  • 查询使用了**非唯一索引**或**范围查询条件**,并且扫描范围覆盖到了索引间隙
  • 例如:SELECT * FROM users WHERE age BETWEEN 25 AND 35 FOR UPDATE; —— 即使表里不存在 age=28 的记录,也可能锁住 (25, 35) 这段间隙

需要注意的是:SELECT ... FOR UPDATE、UPDATE、DELETE 都可能触发间隙锁,而普通的 SELECT(一致性非锁定读)通常不会加这种锁。

等值查询非唯一索引时,记录锁和间隙锁往往会同时出现

这是 MySQL 锁机制实战中最容易让人困惑的地方之一。只要查询条件基于非唯一索引进行等值匹配(例如 WHERE status = 'pending'),InnoDB 加的通常就不只是单纯的记录锁:它会先对每个命中的索引记录加锁,再把这些记录前后的索引间隙一并锁住,最终形成的就是临键锁(Next-Key Lock)。

举例说明:

  • 表 orders 上有非唯一索引 idx_status(status),当前存在 status='pending' 的记录,对应索引值分别为:20、25、30
  • 执行 SELECT * FROM orders WHERE status = 'pending' FOR UPDATE;
  • 实际加锁范围可能包括:(15,20]、(20,25]、(25,30]、(30,35](假设相邻索引值为 15 和 35)

也就是说,看起来你只是锁住了三条 pending 记录,实际上连这些记录之间的空隙,以及前后相邻索引值之间的区域也一起被锁住了。这也是为什么 MySQL 中看似简单的等值查询,在高并发场景下反而容易造成插入阻塞。

判断当前到底加了哪种锁,要看 SHOW ENGINE INNODB STATUS 输出

执行完相关加锁 SQL 后,可以在另一个会话中运行 SHOW ENGINE INNODB STATUSG,重点查看 TRANSACTIONS 段中的 RECORD LOCKS 相关内容:

  • 包含 locks rec but not gap → 表示纯记录锁
  • 包含 locks gap before rec → 表示间隙锁(或临键锁中的间隙部分)
  • 同时出现 locks rec but not gap 和 locks gap before rec → 通常说明表现为临键锁

不要只依赖 explain 或执行计划去推测锁类型——真正可靠的判断依据,是 INNODB STATUS 中展示的锁结构信息,这才是 MySQL 实际加锁行为的直接证据。

最容易被忽略的一点是:间隙锁是否会出现,根本上取决于事务隔离级别和索引类型,而不只是 SQL 写法本身。比如同样一句 WHERE age = 25,在 READ COMMITTED 下,可能根本不会触发间隙锁;但如果切换到 REPEATABLE READ,就有可能把整段空白索引区间一起锁住。因此在系统上线前,一定要在目标数据库隔离级别下实际验证锁行为,这一步非常关键,不能省略。

来源:https://www.php.cn/faq/2994257.html
上一篇Oracle Active Data Guard开启实时查询的方法与步骤 下一篇MySQL触发器是什么及其使用风险解析
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Redis是什么:核心特性、架构与应用场景解析
数据库 · 2026-09-01

Redis是什么:核心特性、架构与应用场景解析

Redis是一款基于内存的键值型NoSQL数据库,以超高读写速度和丰富的数据结构著称。本文系统梳理Redis的核心特性、架构组成、性能优势及典型应用场景,并通过与Memcached、MySQL、MongoDB的对比,帮助开发者快速判断Redis是否适合当前业务需求。

Windows 安装 MongoDB 完整图文教程
数据库 · 2026-09-01

Windows 安装 MongoDB 完整图文教程

本文详细介绍在 Windows 系统上安装 MongoDB 的完整流程。从官网下载 MSI 安装包开始,逐步演示自定义安装路径、配置 Windows 服务、跳过 MongoDB Compass 等关键选项,并提供通过系统服务列表验证安装是否成功的方法,帮助开发者快速搭建本地 MongoDB 环境。

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动
数据库 · 2026-09-01

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动

本文详解在 Linux 系统下安装 MongoDB 的完整流程,涵盖依赖包安装、二进制包下载解压、环境变量配置、数据与日志目录创建及服务启动验证。通过标准化命令与路径说明,帮助开发者快速完成部署并确认服务状态。

MacOS安装MongoDB完整教程
数据库 · 2026-09-01

MacOS安装MongoDB完整教程

本文介绍在MacOS系统下安装MongoDB的完整流程,涵盖下载、解压、目录配置、环境变量设置及服务启动。通过明确的命令与参数说明,帮助开发者快速完成环境搭建并验证安装结果。

Ubuntu系统安装与配置Redis完整指南
数据库 · 2026-09-01

Ubuntu系统安装与配置Redis完整指南

本文详解在Ubuntu系统中安装Redis的两种主流方式:apt在线安装与源码编译安装。涵盖版本选择逻辑、服务启停与状态检查、连接验证方法,以及在线练习工具与桌面GUI客户端的对比与使用建议,帮助开发者快速搭建并验证Redis运行环境。