MySQL 事务隔离级别怎样缩小锁等待范围
来源:17golang原创
时间:2026-10-19 21:15:38 400浏览 收藏
MySQL 事务锁等待不一定要靠降低隔离级别解决。对于 InnoDB 范围更新,如果主要冲突来自范围中的间隙锁,而且业务允许同一事务的多次普通读取看到不同已提交数据,可以考虑 READ COMMITTED;如果两个事务更新的是同一条记录,改成 READ COMMITTED 仍然可能等待。
以下按 MySQL 8.4 官方规则解释,仅讨论隔离级别与锁等待,不给出生产实测结果。官方资料:https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html。
从范围写入识别等待对象
设想一个订单后台:事务 A 调整某租户一段业务编号内的状态,事务 B 同时插入该区间的新订单。此时要先区分 B 是在等插入位置,还是在更新 A 已经修改的记录。两类等待不能用同一个“降级就好”的结论处理。
把请求中的租户编号、范围上下界和操作类型对应到 SQL,再看它实际使用的索引。业务 WHERE 看起来很窄,并不等于执行时扫描的索引范围就窄;缺少合适索引时,隔离级别不是唯一变量。
确认业务能否接受逐次读取变化
采用 READ COMMITTED 之前,要回答“事务内第二次普通查询看到新提交的数据,业务是否还能正确决策”。如果程序依赖两次查询的范围集合不变,放宽规则就可能让后续处理对象发生变化。不能只比较等待时间,却忽略读取口径。
REPEATABLE READ 的普通一致性读与 UPDATE、锁定读也不是同一条读取路径。不要因为先前 SELECT 没看到某条记录,就推断后续写入没有并发冲突。隔离级别选择应落实到具体事务,而非给所有接口贴统一标签。
| 等待或需求 | 应关注的方向 |
|---|---|
| 范围附近插入被阻塞 | 检查间隙锁及业务能否接受 RC |
| 同一已有记录被多个事务更新 | 检查记录冲突及持锁事务时长 |
| 希望多次读取集合保持一致 | 先保留一致性要求,不单为减少等待改设置 |
| 扫描远多于目标记录 | 先检查索引访问范围 |
把索引范围与记录冲突分开
在 REPEATABLE READ 下,非唯一范围搜索可能涉及 next-key 锁及间隙;READ COMMITTED 的相关范围操作通常仅锁索引记录,外键与重复键检查除外。对于 UPDATE、DELETE,不匹配行的记录锁也有较早释放的规则。后者不表示匹配且被修改的记录没有锁。
按唯一索引精确找到一条已有记录,本来就与非唯一范围搜索不同。分析时同时记录访问索引、搜索方式和事务是否结束。锁与扫描范围的官方说明:https://dev.mysql.com/doc/refman/8.4/en/innodb-locks-set.html。

仅为下一笔事务设置隔离级别
对独立测试连接,可以先设置下一笔事务的隔离级别,再开始事务。不要在已经执行 START TRANSACTION 的事务中尝试改变它。
-- 仅影响当前连接的下一笔事务,不修改全局默认值。 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; -- 假设表有主键 (tenant_id, order_no),字段非空。 UPDATE order_lock_demo SET state_code = 2 WHERE tenant_id = 7 AND order_no >= 100 AND order_no
无 SESSION 或 GLOBAL 的 SET TRANSACTION 只作用于下一笔事务;SESSION 会影响连接后续事务,连接复用时更容易把设置带给别的请求。务必在同一物理连接上设置并启动事务,不能让连接池分别分配两条命令。语法与作用域见:https://dev.mysql.com/doc/refman/8.4/en/set-transaction.html。
用两会话对照解释剩余等待
为了对照范围插入和同记录更新,下面提供测试表及两个会话的命令。普通临时表不适合这个跨会话示例,因此使用专用测试库内的 InnoDB 表;确认同名对象不存在后再创建,不在生产库执行。
-- 仅在专用测试库创建一次;两会话必须连接到同一个测试库。
CREATE TABLE order_lock_demo (
tenant_id INT NOT NULL,
order_no INT NOT NULL,
state_code INT NOT NULL,
PRIMARY KEY (tenant_id, order_no)
) ENGINE = InnoDB;
-- 数据中预留编号 150,避开重复键与外键检查的影响。
INSERT INTO order_lock_demo VALUES
(7, 110, 1), (7, 190, 1), (7, 250, 1);
会话 A 先执行下面的范围更新,暂时保留事务。对比时分别在事务开始前选择 REPEATABLE READ 或 READ COMMITTED,其余 SQL 和数据保持一致。
-- 会话 A:该轮使用 RR;下一轮可改为 READ COMMITTED。 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; START TRANSACTION; UPDATE order_lock_demo SET state_code = 2 WHERE tenant_id = 7 AND order_no >= 100 AND order_no
会话 B 每轮只选择下面一个实验。先观察插入,再把两端事务结束、恢复初始状态后观察更新已有记录,不要把几个实验堆在同一笔未结束事务里。
-- 会话 B 实验一:尝试插入 A 搜索范围内的新位置。 START TRANSACTION; INSERT INTO order_lock_demo VALUES (7, 150, 1); -- 命令返回后回滚;若它正在等待,需要先结束会话 A 的事务。 ROLLBACK; -- 会话 B 实验二:在全新一轮中尝试修改 A 已锁定的记录。 START TRANSACTION; UPDATE order_lock_demo SET state_code = 3 WHERE tenant_id = 7 AND order_no = 110; -- 即使 A 使用 RC,同记录写冲突仍可能等待。 ROLLBACK;
在示例前提和对应主键范围访问下,预期 RR 与 RC 在插入空位的行为上可能体现差异,而修改已有记录仍受到记录锁约束。这是供读者自行观察的预期,不是本文已经测出的结果。若现象不同,应保留实际访问路径和锁对象,不能照图猜测。

异常结束后及时释放事务资源
失败路径同样需要明确事务结尾。应用遇到等待超时、取消或其他 SQL 错误时,不要假设所有错误都会替你结束整笔事务。由事务管理层决定回滚,并确认连接可以安全复用;不能把长时间打开的事务交回池中继续持有资源。
演示清理时先让 A 回滚,再等待 B 的命令返回并回滚。两个会话都结束事务后,方可在专用测试库删除示例表。
-- 仅在确认两会话事务都已结束后清理专用测试对象。 DROP TABLE order_lock_demo;
RC 能消除死锁吗?
不能。它可能减少某些锁冲突,但多个事务仍可能争用相同记录;应用需要明确失败处理,不能把隔离级别当作免死锁开关。
能否先全局改成 RC 看效果?
不应把全局变更当作一个接口的排障试探。先限定事务、确认读取语义,并与现有复制及部署要求协调,本文不提供全局修改步骤。
缩短锁等待最先改什么?
先识别等待对象:记录冲突看持锁事务和操作范围;间隙相关冲突才讨论隔离级别。无论选择哪一级,都应让事务只包住必要的数据库操作,并及时结束。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
122 收藏
-
267 收藏
-
258 收藏
-
128 收藏
-
244 收藏
-
304 收藏
-
395 收藏
-
318 收藏
-
464 收藏
-
448 收藏
-
386 收藏
-
166 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习