MySQL 中的事务隔离级别有哪些?
SQL标准定义4种事务隔离级别,InnoDB全部支持,MySQL默认是可重复读 RR 。
隔离级别由低到高:读未提交 → 读已提交 → 可重复读 → 串行化。
三种并发问题(脏读、不可重复读、幻读)
- 脏读 :一个事务读到另一个事务未提交的数据,如果对方回滚,读到的数据就是脏数据。
- 不可重复读 :同一个事务内,同一条SQL多次执行,读到的数据不一样 。别的事务提交修改,本事务读到新数据。重点是:数据内容发生变化。
- 幻读 :同一个事务,同样的查询,前后返回的行数不一样。别的事务插入/删除数据,本事务出现凭空多出或者少行,重点是行数变化。
四个隔离级别
1. Read Uncommitted 读未提交
- 可以读取其他事务还没有提交的数据
- 会出现:脏读、不可重复读、幻读
- 几乎不会线上使用
2. Read Committed(RC)读已提交
- 只能读到其他事务已经提交的数据
- 解决:脏读
- 存在:不可重复读、幻读
- MVCC行为:每次select都生成新的ReadView
很多互联网项目会把隔离级别改成RC,锁冲突更少,并发更高。
3. Repeatable Read(RR)可重复读,MySQL InnoDB默认级别
- 同一个事务内部,多次读取,读到的数据始终是事务启动时的快照
- 解决:脏读、不可重复读
- SQL标准中RR还存在幻读,MySQL的InnoDB通过 MVCC + 间隙锁(临键锁)解决了幻读
- MVCC行为:事务第一次select才生成ReadView,整个事务复用同一个视图
4. Serializable 串行化
- 最高隔离级别,所有普通select隐式转为
select ... share mode,全部加共享锁 - 全部问题都解决:脏读、不可重复读、幻读
- 事务串行执行,并发能力极差,几乎不用。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交 | 存在 | 存在 | 存在 |
| 读已提交RC | 不存在 | 存在 | 存在 |
| 可重复读RR | 不存在 | 不存在 | InnoDB已解决 |
| 串行化 | 不存在 | 不存在 | 不存在 |
补充面试高频考点
- Oracle默认隔离级别是RC,MySQL InnoDB默认RR。
- RC级别没有间隙锁,只有行锁;RR级别才会产生间隙锁、临键锁,用来解决幻读。
- 隔离级别越高,并发性能越差;级别越低,并发越高,但数据一致性问题越多。
总结:
一共4种隔离级别:读未提交、读已提交RC、可重复读RR、串行化;MySQL默认RR;RC每次查询生成ReadView,RR事务首次查询生成ReadView;InnoDB在RR下依靠MVCC+临键锁解决幻读;隔离级别越高一致性越好,并发性能越低。