MySQL 事务隔离级别怎样缩小锁等待范围
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 看效果?
不应把全局变更当作一个接口的排障试探。先限定事务、确认读取语义,并与现有复制及部署要求协调,本文不提供全局修改步骤。
缩短锁等待最先改什么?
先识别等待对象:记录冲突看持锁事务和操作范围;间隙相关冲突才讨论隔离级别。无论选择哪一级,都应让事务只包住必要的数据库操作,并及时结束。
MySQL JSON_MERGE_PATCH 怎样按对象字段合并文档
- 上一篇
- MySQL JSON_MERGE_PATCH 怎样按对象字段合并文档
- 下一篇
- MySQL sys schema 怎样查看表空间使用率
-
- 数据库 · MySQL | 1小时前 |
- MySQL sys schema 怎样查看表空间使用率
- 122浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL JSON_MERGE_PATCH 怎样按对象字段合并文档
- 267浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL optimizer_trace 查看范围优化决策路径的配置方法
- 128浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 大 IN 列表怎样理解索引估算成本
- 244浏览 收藏
-
- 数据库 · MySQL | 1小时前 | 执行计划 · Mysql索引 · mysql 不可见索引 optimizer_switch FORCE INDEX USE INDEX
- MySQL 不可见索引被 USE INDEX 指定时为什么报错
- 304浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL JSON_PRETTY 怎样把 JSON 文档格式化输出
- 395浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL GET DIAGNOSTICS 怎样读取存储程序的错误信息
- 318浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql explain partition pruning 分区裁剪 partitions
- MySQL 怎样从执行计划判断分区裁剪
- 464浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL INSERT IGNORE 怎样识别被忽略的行
- 448浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL histogram 怎样更新列分布统计而不改表结构
- 386浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL LAG 怎样比较相邻日期记录
- 166浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 548次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 601次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 628次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 581次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 405次使用
-
- 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浏览

