MySQL 默认的事务隔离级别是什么?为什么选择这个级别?
- 标签:后端、MySQL、数据库
🏛 业务架构师
MySQL 默认 可重复读(RR),选择它有明确的历史与业务理由:
- 主从复制安全:早期 binlog 以 statement 格式记录 SQL 语句本身,RC 下语句的执行时机不同会导致主从结果不一致(比如 update ... limit 1 在主从选中不同的行),RR 的间隙锁让并发写入排队,语句在主从的执行顺序与结果可控。主从不一致对以复制做容灾的业务是致命的;
- InnoDB 的能力演进:RR 下 InnoDB 用 MVCC 解决不可重复读、用间隙锁基本消除幻读,使 RR 的并发代价变得可接受。
但默认值不等于最优值,我的实践判断:row 格式 binlog 普及后,RC 的复制安全性问题消失,很多互联网公司把核心库改成 RC + row 复制,原因是:
- RC 没有间隙锁,高并发写入的死锁率显著下降——交易高峰的锁等待是真实容量损耗;
- RC 每次查询取最新快照,"读不到刚改的数据"这类体验问题更少。
业务选型结论:以 statement 复制或依赖默认行为的老系统,保持 RR 别乱动;新交易系统用 RC + row + 业务幂等,换并发能力。同时无论哪档,资金操作的强一致不靠隔离级别,靠当前读(select for update)或乐观锁在业务层显式保证——隔离级别是背景板,关键一致性永远要主动设计。
🏗 系统架构师
MySQL 默认 RR(可重复读)。选择理由我从三方面讲:
- 历史正确性诉求:主从复制早期基于 binlog 的 statement 格式,RC 下语句执行顺序不同会导致主从数据不一致(语句如
update ... limit 1),RR + 锁能保证语句执行的可确定性,保证复制安全。这是 RR 成为默认的最根本原因; - 业务友好:同一事务内多次读结果一致,转账"查余额→校验→扣款"这类读后写逻辑不会读到中间状态,应用层心智负担小;
- 性能可接受:InnoDB 的 RR 靠 MVCC 实现,读不加锁,没有早期数据库"串行化级别才有可重复读"的性能悬崖。
但我不迷信它:RC 没有间隙锁、锁范围小、并发度更高,死锁更少,互联网高并发场景(阿里等)大量改用 RC,前提是业务能容忍同事务内不可重复读、并用乐观锁/唯一约束保证写正确性。默认值是通用安全解,架构师要能根据业务一致性假设主动偏离默认。
💻 全栈开发专家
默认 REPEATABLE READ(RR)。历史原因和实现权衡:
- binlog 兼容:早期 binlog 用 STATEMENT 格式(记 SQL 语句),RC 下语句执行顺序在主从可能不同,导致主从不一致。RR 配合间隙锁能锁住语句涉及的范围,保证 STATEMENT 回放安全。后来有了 ROW 格式这个问题其实弱化了,但默认值保留至今。
- 单机强一致观感:RR 一个事务内多次读结果一致,报表/对账类业务友好。
但要说工程实践:现在主流做法是 ROW 格式 binlog + RC 隔离级别,因为:
- RC 没有间隙锁的大范围使用,锁冲突和死锁显著减少(我在订单系统把 RR 改 RC 后死锁告警降了 80%);
- 并发性能更好,长事务下的锁等待更短;
- InnoDB 层 RC 下还能用半一致读优化 update。
面试话术:先答默认 RR 和历史原因,再补一句"ROW 格式时代我实际更倾向 RC,并说明原因",直接把对话带到 MVCC 实现层,主动权就在我手里了。