0
0
0

MySQL 学习笔记:四种事务隔离级别与三种读异常

2026-10-27
文章摘要
|

一、事务隔离级别

MySQL 有四种事务隔离级别,主要用于控制多个事务并发执行时的数据可见性。

隔离级别

脏读

不可重复读

幻读

RU(读未提交)

❌

❌

❌

RC(读已提交)

✅

❌

❌

RR(可重复读)

✅

✅

✅*

Serializable(串行化)

✅

✅

✅

✅ 表示可以防止;❌ 表示可能发生。

MySQL InnoDB 的 RR 通过 MVCC 使普通快照读避免幻读,通过 Next-Key Lock 等锁机制防止适用场景下当前读的幻读,但混用快照读和当前读时仍可能观察到不同结果。

MySQL InnoDB 默认使用 RR(可重复读)。

二、三种读异常

1. 脏读(Dirty Read)

定义:一个事务读取到了另一个事务尚未提交的数据。

假设账户余额为 1000 元。

时间

事务 A

事务 B

T1

修改余额为 500,未提交

T2

查询余额 → 500

T3

ROLLBACK 回滚

T4

余额恢复为 1000

事务 B 读取到了尚未提交的 500,这就是脏读。

注意:即使事务 A 最终提交成功,事务 B 提前读取了未提交数据,仍然属于脏读。

解决方式:RC 及更高级别。

2. 不可重复读(Non-Repeatable Read)

定义:同一个事务内,两次读取同一条记录,读取到的字段值不同。

假设余额为 1000 元。

时间

事务 A

事务 B

T1

SELECT → 1000

T2

UPDATE 余额 = 500

T3

COMMIT

T4

SELECT → 500

事务 A 两次读取同一条记录,第一次是 1000,第二次是 500。

这是不可重复读。

解决方式:RR 及更高级别。

在 InnoDB RR 中,同一事务内的普通快照读通常复用第一次一致性读创建的 Read View,所以能够保持读取结果一致。

3. 幻读(Phantom Read)

定义:同一个事务内,两次按照相同条件查询,发现符合条件的记录集合发生变化,典型情况是其他事务插入了新记录。

例如:

SELECT * FROM user WHERE age > 20;

时间

事务 A

事务 B

T1

查询出 5 条记录

T2

INSERT 一条 age=25 的记录

T3

COMMIT

T4

再次查询,可能得到 6 条记录

事务 A 发现符合条件的记录多出了一条,就像出现了“幻影”。

解决方式:Serializable 可以防止幻读。MySQL InnoDB 的 RR 也通过 MVCC 和间隙锁、Next-Key Lock 等机制,在相应读取场景下避免幻读。

三、四种隔离级别分别解决什么问题?

隔离级别

主要特点

RU

可以读取未提交数据,可能发生脏读

RC

只能读取已提交数据,解决脏读

RR

解决脏读、不可重复读;InnoDB 还能在常见场景下避免幻读

Serializable

隔离最严格,防止三种读异常,但并发能力受限制

RC 与 RR 的核心区别

对于普通快照读:

  • RC: 每条 SELECT 通常创建新的 Read View,因此可以读取其他事务最新提交的数据。

  • RR: 第一次一致性读创建 Read View,后续一致性读通常复用,因此能保证可重复读。

注意:SELECT ... FOR UPDATE、UPDATE、DELETE 属于当前读或需要读取当前版本的操作,不能直接套用上述快照读规则。

四、面试总结

问题 1:什么是脏读?

读取到了其他事务尚未提交的数据。重点是“未提交”,而不是数据与最终结果是否一致。

问题 2:脏读和不可重复读有什么区别?

脏读关注数据是否提交;不可重复读关注同一事务内两次读取同一条记录,结果是否发生变化。

问题 3:不可重复读和幻读有什么区别?

不可重复读主要关注同一条记录的字段值变化;幻读主要关注符合查询条件的记录集合发生变化。

问题 4:为什么 RR 可以实现可重复读?

因为 InnoDB 通过 MVCC 和 Read View 实现一致性读。在 RR 下,同一事务的普通快照读通常复用同一个 Read View。

问题 5:MySQL 默认隔离级别是什么?

InnoDB 默认使用 RR(可重复读)。


五、重点记忆

  • 脏读: 读到了别人还没提交的数据。

  • 不可重复读: 同一事务,两次读取同一条记录,值发生变化。

  • 幻读: 同一事务,两次相同条件查询,符合条件的记录集合发生变化。

  • RC: 解决脏读。

  • RR: 解决不可重复读,InnoDB 还能在常见场景下避免幻读。

  • Serializable: 隔离最严格,防止三种读异常。

一句话总结:脏读看是否提交,不可重复读看记录值变化,幻读看记录集合变化。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

评论