MySQL 的事务隔离级别是为了解决并发事务中可能出现的数据不一致问题(如脏读、不可重复读、幻读)。MySQL 提供了 四种事务隔离级别,从低到高依次为: 读未提交、读已提交、可重复读、串行化。
一. 四种隔离级别
1. 读未提交(Read Uncommitted, RU)
- 特点:
- 允许事务读取其他事务 未提交 的修改(即“脏读”)。
- 所有并发问题都可能发生(脏读、不可重复读、幻读)。
- 性能最高,因为没有加锁或快照机制。
- 适用场景:
- 对数据一致性要求极低的场景(如数据分析或报表系统),但需接受数据可能不准确的风险。
- 示例:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
2. 读已提交(Read Committed, RC)
- 特点:
- 事务只能读取其他事务 已提交 的修改(避免脏读)。
- 不可重复读 和 幻读 仍可能发生。
- 每次查询生成新的快照(基于 MVCC),可能导致同一事务内多次查询结果不一致。
- 适用场景:
- 大多数数据库默认级别(如 Oracle),适用于对数据一致性要求中等、但需较高并发性能的 OLTP 系统。
- 示例:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
3. 可重复读(Repeatable Read, RR)
- 特点:
- MySQL 默认隔离级别(InnoDB 引擎)。
- 事务执行期间多次读取同一数据的结果始终一致(避免脏读和不可重复读)。
- InnoDB 通过 MVCC 和间隙锁 解决幻读问题(标准 RR 仅避免脏读和不可重复读,但 InnoDB 扩展了功能)。
- 事务级别的快照(MVCC)保证一致性。
- 适用场景:
- 高并发的 OLTP 系统(如银行转账、电商订单处理),需兼顾数据一致性和性能。
- 示例:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
4. 串行化(Serializable, SERIALIZABLE)
- 特点:
- 最高隔离级别,强制事务 串行执行,完全避免脏读、不可重复读和幻读。
- 通过表级锁或行级锁 阻止其他事务的并发操作,导致 性能最低。
- 适用于对数据一致性要求极高的场景,但可能导致大量超时和锁竞争。
- 适用场景:
- 数据一致性要求极高但并发性要求低的场景(如金融系统的最终一致性校验)。
- 示例:
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
二、隔离级别与并发问题的关系
隔离级别 | 脏读 | 不可重复读 | 幻读 | MySQL 实际表现(InnoDB) |
---|---|---|---|---|
读未提交(RU) | ✅ | ✅ | ✅ | 允许所有并发问题 |
读已提交(RC) | ❌ | ✅ | ✅ | 避免脏读,允许不可重复读和幻读 |
可重复读(RR) | ❌ | ❌ | ✅ | InnoDB 通过间隙锁和 MVCC 解决幻读 |
串行化(Serializable) | ❌ | ❌ | ❌ | 完全避免所有并发问题 |
三、如何查看和设置隔离级别
- 查看当前隔离级别:
SHOW VARIABLES LIKE 'transaction_isolation';
- 设置隔离级别:
-- 设置当前会话的隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL <level>; -- 设置全局隔离级别(影响所有新连接) SET GLOBAL TRANSACTION ISOLATION LEVEL <level>;
四、InnoDB 的 RR 级别为何能避免幻读?
MySQL 的 InnoDB 引擎在 可重复读(RR) 级别下通过以下机制避免幻读:
- MVCC(多版本并发控制):
- 通过快照读(Snapshot Read)保证事务看到的数据版本一致。
- 间隙锁(Gap Lock):
- 锁定索引记录之间的“间隙”,防止其他事务插入新数据导致幻读。
- 临键锁(Next-Key Lock):
- 间隙锁 + 行锁的组合,锁定一个范围并包含记录本身。
五、实际选择建议
- 默认使用 RR:InnoDB 的 RR 级别在大多数场景下能提供良好的一致性与性能平衡。
- RC 的适用性:如果业务对幻读容忍度较高,且希望减少锁开销,可选择 RC。
- 避免使用 RU:除非对性能极度敏感且能接受数据不一致风险。
- 谨慎使用 SERIALIZABLE:仅在必须完全隔离的场景下使用,需权衡性能代价。
通过合理选择事务隔离级别,可以在数据一致性和系统性能之间找到最佳平衡点。