MySQL默认隔离级别是REPEATABLE READ,根本原因是早期STATEMENT格式binlog下RC会导致主从执行逻辑错位;RR通过Next-Key Lock强制写操作串行化,确保binlog与物理执行一致。

MySQL 默认用 REPEATABLE READ,不是因为“更强一致性”更值得推荐,而是早期主从复制机制下的一种被动兼容设计——STATEMENT 格式 binlog + READ COMMITTED 会直接导致主从数据不一致。
RR 是为堵住 STATEMENT binlog 的执行顺序漏洞
在 MySQL 5.1 之前,binlog 只支持 STATEMENT 格式,它只记录 SQL 文本,不记录实际影响的行。当两个事务并发操作同一索引范围时:
- Session A 执行
DELETE FROM t WHERE c_id = 2(未提交) - Session B 紧接着插入
INSERT INTO t VALUES (100, 2)并提交 - Session A 最终提交 → 主库物理执行是“先删后插”,但 binlog 按提交顺序记为“先插后删”
- 从库回放时严格按 binlog 顺序执行 → 先插再删 → 数据比主库多或少一行
REPEATABLE READ 靠 Next-Key Lock(行锁 + 间隙锁)强制串行化:Session A 的 DELETE 会锁住 c_id = 2 对应的整个索引区间,Session B 的插入被阻塞,直到 A 提交。这样 binlog 记录顺序与物理执行顺序就一致了。
MySQL 数据库管理技能,能够通过自然语言查询和管理数据库,支持 SELECT/INSERT/UPDATE/DELETE、表管理、备份恢复等操作。当用户提及 MySQL、数据库查询、建表或数据备份时使用此技能。
RC 在 ROW 格式下其实已无主从风险
当前生产环境基本都启用 binlog_format = ROW,binlog 直接记录变更的行,不再依赖 SQL 执行顺序。此时 READ COMMITTED 不再引发主从错位。
-
ROW格式下,RC和RR在复制安全性上已无实质差异 - 但默认值没改,是因为大量 ORM、中间件(如
ShardingSphere)、业务逻辑隐式依赖RR的快照行为和锁语义 - 比如某些校验逻辑假定“同一个事务内两次
SELECT结果相同”,换RC就可能出问题
为什么大厂敢切 RC?关键在配套改造
阿里、美团等切换到 READ COMMITTED,不是简单改个配置,而是整套协同落地:
- 必须确认
binlog_format = ROW已全局生效 - 禁用或重写依赖“事务内快照一致性”的业务代码(例如跨查询做金额对账)
- 评估长事务对 undo 日志的影响:
RR下长事务会阻碍 purge,RC每次查询新建ReadView,压力更小 - 监控死锁日志,确认间隙锁移除后,原被阻塞的插入场景是否真能提升吞吐
真正容易被忽略的是:RR 的“安全”只在 STATEMENT binlog 下是刚需;一旦用 ROW,它的锁开销和 MVCC 版本链膨胀就成了纯成本。要不要切 RC,不看默认值是否“权威”,而要看你的 binlog 格式、事务模式、业务校验逻辑是否真的扛得住变化。

















