MySQL 事务、隔离级别与 MVCC(概念速通)
知识背景
事务把多条 SQL 捆成原子单元:ACID(原子性、一致性、隔离性、持久性)。隔离级别决定并发事务之间「能看到彼此未提交修改」的程度;InnoDB 通过 MVCC(多版本并发控制) 与锁配合,在性能与一致性之间折中。
Spring里 @Transactional 最终会把隔离级别传给数据库会话;理解隔离级别有助于排查「读不到刚写的」「幻读」等问题。
知识详解与通俗解释
1. 四个隔离级别(由低到高)
| 级别 | 脏读 | 不可重复读 | 幻读(简化) |
|---|---|---|---|
| 读未提交 RU | 可能 | 可能 | 可能 |
| 读已提交 RC | 否 | 可能 | 可能 |
| 可重复读 RR(InnoDB 默认) | 否 | 否 | 多数场景由间隙锁/MVCC 控制 |
| 串行化 Serializable | 否 | 否 | 否 |
- 脏读:读到别事务未提交的数据。
- 不可重复读:同一事务两次读同一行,中间被别事务修改并提交,值变了。
- 幻读:同一范围查询两次,多出「新插入」的行(强调「多行」语义时与不可重复读区分)。
通俗说:隔离级别像「包厢隔音」:越严越安静,但并发越差。
2. MVCC 直觉
每行可有多版本;事务启动时看可见性规则决定读哪个版本,使普通读少加锁、提高并发。具体由 undo log、Read View 等实现,面试答到「快照读、版本链」即可再深入。
3. 与 Spring 事务传播
@Transactional 的 传播行为、rollbackFor、只读事务 会改变事务边界;隔离级别可在注解或全局数据源配置。只读事务在只查询场景可帮助优化(具体行为依赖数据库与驱动)。
4. 长事务风险
长事务持有锁、拖长 undo、增大 MVCC 可见性开销,易导致锁等待与性能抖动——业务上应拆事务、避免远程调用包在大事务里。
总结
- InnoDB 默认 RR,依赖 MVCC + 锁 实现隔离语义。
- 现象排查:先确认隔离级别与是否快照读,再看锁与执行计划。
- 与 MP 无关但和所有写库代码有关:事务边界设计比 ORM 技巧更底层。