事务的隔离级别(Isolation Level)是指:多个事务并发执行时,数据库为保证事务隔离所采取的措施强度。不同的隔离级别会影响系统的并发性能和数据一致性。
在 MySQL(InnoDB 引擎)中,一共有四种标准隔离级别:
隔离级别 | 能解决的问题 | 可能发生的问题 | 并发性 |
---|---|---|---|
读未提交(Read Uncommitted) | - | 脏读 | 高 |
读已提交(Read Committed) | ✅ 脏读 | 不可重复读 | 较高 |
可重复读(Repeatable Read)【MySQL 默认】 | ✅ 脏读 ✅ 不可重复读 |
幻读 | 中等 |
串行化(Serializable) | ✅ 脏读 ✅ 不可重复读 ✅ 幻读 |
- | 低(性能最差) |
举例:
T1: UPDATE account SET balance = balance - 100 WHERE id = 1; // 还没提交
T2: SELECT balance FROM account WHERE id = 1; // 看到减少后的余额
T1: ROLLBACK; // 回滚
➡️ T2 读到的是一个“假的余额”,这就是脏读。
举例:
T1: SELECT balance FROM account WHERE id = 1; // 余额 = 1000
T2: UPDATE account SET balance = 800 WHERE id = 1;
COMMIT;
T1: SELECT balance FROM account WHERE id = 1; // 余额 = 800
➡️ T1 两次读到不同值,称为不可重复读
举例:
T1: SELECT * FROM user WHERE age > 18; // 查出10条
T2: INSERT INTO user (name, age) VALUES ('张三', 20);
COMMIT;
T1: 再次 SELECT * FROM user WHERE age > 18; // 看到11条
➡️ 出现了“幻影”数据 —— 这就是幻读。
⚠️ 但是!InnoDB 使用间隙锁(Gap Lock)避免了幻读的发生,所以MySQL 实际上避免了幻读!
下面这张图可视化地表示了各种隔离级别与并发问题之间的关系:
它在性能和一致性之间做了最佳平衡。配合 MVCC(多版本并发控制) 和 间隙锁,可以防止大部分问题。
MySQL 的 InnoDB 使用 间隙锁(Gap Lock) 来锁住可能插入的位置,从而避免幻读。
只适用于 Read Committed 和 Repeatable Read,因为它依赖多版本快照来读取旧数据。
在 MySQL 的默认隔离级别(可重复读)下,如果事务 A 修改了数据但未提交,事务 B 将看到修改之前的数据。
这是因为在可重复读隔离级别下,MySQL 将通过多版本并发控制(MVCC)机制来保证一个事务不会看到其他事务未提交的数据,从而确保读一致性。
使用
SET SESSION TRANSACTION ISOLATION LEVEL
可以修改当前连接的隔离级别,只影响当前会话。
使用SET GLOBAL TRANSACTION ISOLATION LEVEL
可以修改全局隔离级别,影响新的连接,但不会改变现有会话。