MySQL 中的事务隔离级别用于控制事务之间的可见性,确保数据库在高并发场景下的数据一致性。MySQL 支持四种事务隔离级别,从低到高依次为:
1. 读未提交(Read Uncommitted)
- 定义:允许一个事务读取另一个事务尚未提交的修改。
- 问题:
- 脏读(Dirty Read):事务可能读取到其他事务未提交的数据(如果该事务回滚,读取的数据是无效的)。
- 不可重复读(Non-Repeatable Read):同一事务内多次读取同一数据,结果可能不一致(其他事务提交了修改)。
- 幻读(Phantom Read):同一事务内多次查询满足条件的记录,结果集可能增加或减少(其他事务插入/删除数据)。
- 适用场景:对数据一致性要求极低的场景,如统计类操作,但实际很少使用。
2. 读已提交(Read Committed)
- 定义:一个事务只能读取到其他事务已经提交的修改。
- 解决的问题:
- 防止脏读。
- 存在的问题:
- 不可重复读:同一事务内多次读取同一数据,结果可能不一致。
- 幻读:同一事务内多次查询结果集可能变化。
- 实现机制:
- MVCC(多版本并发控制):通过快照读(Snapshot Read)实现非阻塞读。
- 锁机制:写操作需要加锁(如行锁),防止脏写。
- 适用场景:大多数数据库的默认隔离级别(如 Oracle、PostgreSQL),适合需要避免脏读但允许短时数据不一致的场景。
3. 可重复读(Repeatable Read)
- 定义:事务在执行期间多次读取同一数据时,结果始终一致(即使其他事务提交了修改)。
- 解决的问题:
- 防止脏读。
- 防止不可重复读。
- 存在的问题:
- 幻读(标准 SQL 的定义):但在 InnoDB 存储引擎 中通过 Next-Key Lock 机制解决了幻读问题。
- 实现机制:
- MVCC:保证事务内读取的快照一致性。
- Next-Key Lock:行锁 + 间隙锁,防止其他事务插入新记录(解决幻读)。
- 适用场景:MySQL 的默认隔离级别(InnoDB),适用于大多数业务场景,如金融系统、订单处理等。
4. 串行化(Serializable)
- 定义:所有事务依次串行执行,完全隔离。
- 解决的问题:
- 防止脏读。
- 防止不可重复读。
- 防止幻读。
- 缺点:
- 性能开销大:事务串行执行,可能导致大量等待,降低并发性。
- 实现机制:
- 锁机制:对所有读写操作加锁,包括范围锁(如表锁、间隙锁)。
- 适用场景:对数据一致性要求极高且并发量较低的场景,如银行核心交易系统。
事务隔离级别与并发问题的关系
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(RU) | √ | √ | √ |
读已提交(RC) | × | √ | √ |
可重复读(RR) | × | × | ×(InnoDB) |
串行化(S) | × | × | × |
如何查看和设置隔离级别?
- 查看当前隔离级别:
-- MySQL 8.0 之前
SELECT @@tx_isolation;
-- MySQL 8.0 及以上
SELECT @@transaction_isolation;
- 设置隔离级别:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE};
SESSION
:仅对当前会话生效。GLOBAL
:对所有新会话生效。
选择隔离级别的原则
- 一致性 vs. 性能:
- 隔离级别越高,数据一致性越强,但性能损耗越大。
- 通常选择 可重复读(RR) 或 读已提交(RC)。
- 业务需求:
- 如果业务允许短时数据不一致(如统计类操作),可使用 RC。
- 如果业务要求严格一致性(如金融交易),可使用 RR 或 S。
补充:InnoDB 中可重复读(RR)的特殊性
- 标准 SQL 的 RR:无法完全避免幻读。
- InnoDB 的 RR:通过 Next-Key Lock(行锁 + 间隙锁)防止幻读,实际效果等同于 Serializable,但性能优于串行化。
总结
- 默认级别:MySQL 的 InnoDB 存储引擎默认使用 可重复读(RR),结合 MVCC 和锁机制,既能保证一致性,又能兼顾性能。
- 选择建议:根据业务需求权衡一致性与性能,避免过度使用高隔离级别导致性能瓶颈。
THE END