MySQL 事务隔离级别下间隙锁影响范围的分析方法
MySQL InnoDB 里看到“插入被卡住”,先不要直接判断成表锁。更常见的原因是事务隔离级别、索引条件和扫描范围共同决定了间隙锁覆盖的区间。分析时按“隔离级别 → 实际使用的索引 → 区间前后的索引记录 → 锁等待方”四步还原,通常就能解释阻塞点。
官方参考:https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html
- InnoDB 默认是 REPEATABLE READ,范围型锁定读会使用间隙锁或临键锁防止范围内插入。
- 唯一索引的完整等值条件通常只锁命中的索引记录;非唯一条件或范围扫描要看扫描到的索引区间。
- 排查重点是锁在哪个索引上、阻塞哪个间隙,以及事务何时提交,而不是只看 SQL 表名。
先区分快照读和真正的锁定读
普通 SELECT 默认是非锁定一致性读,不会因为读到了某个范围就自动把插入挡住。SELECT ... FOR UPDATE、SELECT ... FOR SHARE,以及修改数据的 UPDATE、DELETE 才会按照索引扫描获取锁。先在同一个会话查看隔离级别,避免把快照读和锁定读混在一起。
-- 查看当前会话的隔离级别;排查时优先确认会话值
SELECT @@SESSION.transaction_isolation;
-- 只在明确需要锁定范围时使用 FOR UPDATE
START TRANSACTION;
SELECT id, score FROM exam_result
WHERE score BETWEEN 80 AND 90
FOR UPDATE;
-- 业务处理完成后尽快提交,避免锁随事务长时间保留
COMMIT;
默认的 REPEATABLE READ 会在范围型锁定读中使用 next-key locking;切换到 READ COMMITTED 后,普通搜索和索引扫描通常不再使用间隙锁,但外键检查和重复键检查仍可能需要它。
按索引顺序把间隙锁画成区间

间隙锁锁的不是一行数据,而是索引顺序中两条记录之间“不允许插入”的位置。临键锁则是“索引记录锁 + 该记录之前的间隙锁”。假设索引值为 10、11、13、20,可能观察到的临键区间是 (-∞,10]、(10,11]、(11,13]、(13,20] 和 (20,+∞)。最后一个区间对应最大值之后的 supremum 伪记录。

因此,WHERE score BETWEEN 80 AND 90 FOR UPDATE 是否阻塞新插入,不能只看结果集中返回了几行,还要看优化器沿哪个索引扫描、扫描从哪条记录开始、在哪条记录结束。没有合适索引时,扫描范围和锁持有量都可能扩大。
唯一等值与范围条件要分开判断
完整使用唯一索引做等值查找,例如主键 id = 100,InnoDB 通常只需要锁住命中的索引记录,不必锁住它之前的间隙。若唯一索引只使用了部分列,或者条件落在非唯一索引、范围谓词上,就不能套用这个结论。
| 条件 | 常见锁范围 | 插入判断 |
|---|---|---|
| 完整唯一索引等值 | 记录锁为主 | 邻近间隙通常可插入 |
| 非唯一索引等值 | 扫描到的记录及前方间隙 | 可能阻塞相同范围的新值 |
| 范围条件 | 索引扫描区间的间隙/临键锁 | 区间内插入可能等待 |
| READ COMMITTED 普通扫描 | 通常只保留记录锁 | 更容易插入,但要接受幻读边界 |
这个表只能作为定位起点。真正结论要用 EXPLAIN 确认索引和访问类型,再用锁等待信息确认实际持锁对象。
用两个会话复现“插入等待”
准备一个有索引的表。会话 A 先锁定分数区间但不提交,会话 B 尝试插入区间内的新分数;如果 B 等待,说明它撞上的是 A 扫描范围设置的抑制性间隙锁,而不一定是某一条已存在的行。
-- 会话 A:锁住索引范围,故意保持事务未提交
START TRANSACTION;
SELECT id FROM exam_result
WHERE score BETWEEN 80 AND 90
FOR UPDATE;
-- 会话 B:新值落入同一索引区间时可能等待
START TRANSACTION;
INSERT INTO exam_result(id, score) VALUES (901, 85);
-- 这里的等待对象应结合 data_locks 判断,不要只看客户端卡顿
ROLLBACK;
复现时同时记录 SHOW CREATE TABLE、EXPLAIN 和两会话的提交时间。若谓词没有命中预期索引,先解释“实际扫描了什么”,再讨论锁范围;否则很容易把索引设计问题误判为隔离级别问题。
用锁等待信息收敛处理方案
MySQL 8.4 可从 Performance Schema 的 data_locks 和 data_lock_waits 观察等待关系。重点看阻塞事务、请求事务、表名、索引名和锁类型;事务是否长时间不提交,往往比“是不是间隙锁”更直接地决定事故持续时间。
-- 查看等待边:谁在等、谁在阻塞
SELECT w.REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx,
w.BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx
FROM performance_schema.data_lock_waits AS w;
-- 收敛方案:缩小索引范围、缩短事务、提前提交
-- 只有业务允许出现幻读时,才评估 READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
生产环境的判断清单是:索引是否覆盖过滤条件;是否能把锁定读改成唯一等值;事务是否夹带了网络调用;是否必须保持范围内不可插入;切换隔离级别后是否接受幻读和日志格式约束。先缩短持锁时间,再考虑放宽隔离级别。
常见问题
间隙锁会锁住一整张表吗?
它锁的是索引间隙,范围过大或缺少合适索引时效果可能接近“谁都插不进去”,但概念上仍不是表锁。
两个事务能同时持有同一间隙锁吗?
间隙锁是抑制插入的锁,不同事务的间隙锁可以共存;真正插入时才会与该间隙上的抑制关系发生等待。
把隔离级别改成 READ COMMITTED 就一定解决吗?
不一定。它通常减少普通扫描的间隙锁,但外键和重复键检查仍可能加锁,记录锁冲突和长事务也不会自动消失。
奶油黄纸页手机壁纸用极简纸张纹理承载日期信息
- 上一篇
- 奶油黄纸页手机壁纸用极简纸张纹理承载日期信息
- 下一篇
- Go errors.As提取自定义错误类型的分层处理方案
-
- 数据库 · MySQL | 3天前 |
- MySQL EXPLAIN ANALYZE定位排序临时表的排查方法
- 434浏览 收藏
-
- 数据库 · MySQL | 3天前 | MySQL · JSON ·
- MySQL JSON多值索引处理数组成员检索的设计要点
- 404浏览 收藏
-
- 数据库 · MySQL | 3天前 | MySQL · 数据库 · mysql SQL JSON JSON_TABLE
- MySQL JSON_TABLE为缺失字段提供默认值的映射方法
- 445浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL CTE拆分多阶段聚合查询的维护方法
- 418浏览 收藏
-
- 数据库 · MySQL | 3天前 | MySQL · 数据库 · mysql 窗口函数 ROW_NUMBER RANK DENSE_RANK
- MySQL窗口函数按分组取排名前N条的查询设计
- 465浏览 收藏
-
- 数据库 · MySQL | 3天前 | MySQL · InnoDB · MySQL锁等待 performance_schema.data_lock_waits data_locks锁对象 InnoDB事务阻塞 锁等待链定位
- MySQL 锁等待定位事务锁等待链的实现方法
- 497浏览 收藏
-
- 数据库 · MySQL | 3天前 | MySQL · 连接池 · database/sql ·
- MySQL 连接池配置连接池避免拿到失效连接的实现方法
- 392浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 187次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 243次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 201次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 183次使用
-
- CMMLU
- 深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
- 172次使用
-
- MySQL JSON_TABLE 展开数组时如何保留缺失字段
- 2026-09-10 501浏览
-
- MySQL 分区表怎么处理跨分区唯一键:分区列约束与建表取舍
- 2026-08-30 501浏览
-
- MySQL权限管理设置全攻略
- 2026-03-29 501浏览
-
- MySQL分片实现方法及常见方案解析
- 2025-06-24 501浏览
-
- MySQL表空间碎片怎么清理?超详细优化教程
- 2025-06-13 501浏览

