当前位置: 首页 > news >正文

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 可以修改全局隔离级别,影响新的连接,但不会改变现有会话。

相关文章:

  • python 列表,元组 操作
  • 06-DevOps-自动构建Docker镜像
  • 常用绑定事件方式有哪几种
  • 最新Spring Security实战教程(十一)CSRF攻防实战 - 从原理到防护的最佳实践
  • 机器视觉--Python补充知识
  • MySQL数据备份
  • 相关无关,线性表示经典强化例题
  • 【远程管理绿联NAS】家庭云存储无公网IP解决方案:绿联NAS安装内网穿透
  • 【C++11】深度剖析 C++11 智能指针:告别内存泄漏
  • Spring开篇
  • 【Leetcode】16. 最接近的三数之和
  • 基于“理采存管用”的数据中台建设方案
  • Linux系统编程学习 day4 进程
  • mpstat指令介绍
  • [Java]Map和Set
  • AIBOX集成接口协议 V1.0
  • Sysstat学习入门
  • 一台 Master 多节点玩转 Kubernetes:sealos 一键部署实践
  • Proxmox VE 用户与权限管理命令大全
  • 2025年4月16日华为笔试第一题100分
  • 铁路12306回应“五一前大量放票”传闻:个别方向和区段出现新增票额,均即时进入系统重新发售
  • 水利部将联合最高检开展黄河流域水生态保护专项行动
  • 央行4月开展12000亿元买断式逆回购操作
  • 马上评丨上热搜的协和“4+4”模式,如何面对舆论审视
  • 习近平在上海考察
  • 烟花、美食和购物优惠都安排上了,上海多区开启热闹模式