mysql默认rr是历史包袱而非设计优选,因5.0前statement格式binlog下rc会导致主从不一致(如先删后插被重放为先插后删),rr靠间隙锁“凑巧”规避;row格式引入后该限制消失,但默认值未改。

MySQL默认RR是历史包袱,不是设计优选
MySQL默认REPEATABLE-READ,根本原因不是它更合理,而是5.0及以前binlog_format = STATEMENT时,RC会导致主从数据不一致——主库执行DELETE再INSERT,从库按binlog顺序回放变成先INSERT再DELETE,结果多出一条记录。RR靠间隙锁让并发插入被阻塞,反而“凑巧”规避了这个问题。这个限制在MySQL 5.1引入ROW格式后就没了,但默认值一直没改。
RC在现代生产环境里反而更稳
RR的“可重复读”在长事务下容易引发实际问题:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
Innodb_row_lock_waits飙升:间隙锁范围大,WHERE id > 100可能锁住整个索引区间,写冲突频繁 - undo log膨胀:事务长时间不提交,
ReadView一直挂着,purge线程无法清理旧版本,ibdata1持续增长 - 幻读误判:应用层用“先查后更”逻辑(如
SELECT stock FROM item WHERE id=1再UPDATE ... SET stock = stock - 1),RR下看到的是旧快照,RC下至少能读到最新已提交值,配合UPDATE ... WHERE id = 1 AND stock >= 1原子判断更安全
切换到RC必须同步改代码,不能只调参数
直接执行SET GLOBAL transaction_isolation = 'READ-COMMITTED'只是第一步,真正关键的是应用适配:
- 所有
UPDATE语句的WHERE条件必须足够精确,强烈建议含主键或唯一键,避免RC下因读到旧值导致误更新 - 禁用“查-改-存”三段式逻辑,改用带条件的单条
UPDATE或INSERT ... ON DUPLICATE KEY UPDATE - 监控慢查询里是否突然出现
Waiting for table metadata lock——RC下锁等待模式变了,原来不卡的SQL可能变卡 - 确认业务能接受“非可重复读”:比如用户中心页刷新看到余额+100,再刷变成+200,这在RC下完全合法
MySQL 8.0+ 的隐性RC倾向容易被忽略
即使你没改隔离级别,只要用了binlog_format = ROW + slave_parallel_type = LOGICAL_CLOCK(现在主从并行复制默认配置),从库回放时的可见性行为其实更接近RC语义——因为ROW格式记录的是最终变更,而不是SQL执行过程。这意味着主库设为RR,但从库读到的数据可能已经“提前看到”其他事务提交的结果。这种主从不一致不是bug,而是复制机制带来的天然差异,需要在读写分离架构中特别注意。










