欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > MySQL 事务隔离级别全解析:从脏读到幻读的防线之战

MySQL 事务隔离级别全解析:从脏读到幻读的防线之战

2025/4/20 19:14:06 来源:https://blog.csdn.net/m0_73748193/article/details/147310548  浏览:    关键词:MySQL 事务隔离级别全解析:从脏读到幻读的防线之战

事务的隔离级别(Isolation Level)是指:多个事务并发执行时,数据库为保证事务隔离所采取的措施强度。不同的隔离级别会影响系统的并发性能数据一致性

在 MySQL(InnoDB 引擎)中,一共有四种标准隔离级别:


🔒 MySQL 的四种事务隔离级别

隔离级别能解决的问题可能发生的问题并发性
读未提交(Read Uncommitted)-脏读
读已提交(Read Committed)✅ 脏读不可重复读较高
可重复读(Repeatable Read)【MySQL 默认】✅ 脏读
✅ 不可重复读
幻读中等
串行化(Serializable)✅ 脏读
✅ 不可重复读
✅ 幻读
-低(性能最差)

在这里插入图片描述


📖 各隔离级别详解 + 场景举例

① 读未提交(Read Uncommitted)

  • 读未提交是最低的隔离级别,在这个级别,当前事务可以读取未被其他事务提交的数据,以至于会出现“脏读”(允许读取未提交的数据)、“不可重复读”和“幻读”的问题。
  • 场景:一个事务读取了另一个事务未提交的修改,如果对方回滚,你就读到了不存在的数据!

举例:

T1: UPDATE account SET balance = balance - 100 WHERE id = 1;  // 还没提交
T2: SELECT balance FROM account WHERE id = 1;  // 看到减少后的余额
T1: ROLLBACK;  // 回滚

➡️ T2 读到的是一个“假的余额”,这就是脏读。


② 读已提交(Read Committed)

  • 在读已提交级别,当前事务只能读取已经被其他事务提交的数据
  • 避免了脏读
  • 但是:一个事务中两次读取同一条记录,结果可能不同(不可重复读),不可重复读和幻读问题仍然存在。

举例:

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 两次读到不同值,称为不可重复读


③ 可重复读(Repeatable Read)⭐MySQL 默认

  • 可重复读:一个事务在执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,一个事务内多次读取的结果一致
  • 防止脏读 + 不可重复读
  • 但可能发生幻读:新增记录可能“凭空”出现!

举例:

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 实际上避免了幻读


④ 串行化(Serializable)

  • 最严格的隔离级别
  • 每个事务串行执行,完全锁表
  • 避免所有并发问题:脏读、不可重复读、幻读
  • 会导致大量的锁竞争问题,性能极差,几乎不适用于高并发

🎯 Mermaid 图:事务隔离级别与并发问题对照图

下面这张图可视化地表示了各种隔离级别与并发问题之间的关系:

允许
允许
允许
禁止
允许
允许
禁止
禁止
允许
禁止
禁止
禁止
Read Uncommitted
脏读
不可重复读
幻读
Read Committed
Repeatable Read
Serializable

🧠 面试延伸点 & 易错点

Q1:为什么 MySQL 默认使用 Repeatable Read?

它在性能和一致性之间做了最佳平衡。配合 MVCC(多版本并发控制)间隙锁,可以防止大部分问题。

Q2:怎么解决幻读?

MySQL 的 InnoDB 使用 间隙锁(Gap Lock) 来锁住可能插入的位置,从而避免幻读。

Q3:MVCC 适用于哪个隔离级别?

只适用于 Read CommittedRepeatable Read,因为它依赖多版本快照来读取旧数据。

Q4:A 事务未提交,B 事务上查询到的是旧值还是新值?

在 MySQL 的默认隔离级别(可重复读)下,如果事务 A 修改了数据但未提交,事务 B 将看到修改之前的数据
这是因为在可重复读隔离级别下,MySQL 将通过多版本并发控制(MVCC)机制来保证一个事务不会看到其他事务未提交的数据,从而确保读一致性

Q5:怎么更改事务的隔离级别?

使用 SET SESSION TRANSACTION ISOLATION LEVEL 可以修改当前连接的隔离级别,只影响当前会话。
使用 SET GLOBAL TRANSACTION ISOLATION LEVEL 可以修改全局隔离级别,影响新的连接,但不会改变现有会话。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词