知识点深化 · 数据库 · 事务
事务与 ACID:隔离级别、幻读/不可重复读、MVCC
事务是一组要么全成功要么全失败的操作。ACID 里最复杂的是隔离性:多个事务并发时会有脏读、不可重复读、幻读。四种隔离级别逐级解决,而 InnoDB 用 MVCC 多版本实现读写不阻塞。这一页讲透。
① 小白第一课怎么学(4 步走,约 60 分钟)
别急着背代码,先按这四步建立直觉:
1看图建立直觉(10 分钟)
读②③:并发事务互相干扰。
2记隔离级别(15 分钟)
读④:四种级别对应三种现象。
3手推现象(20 分钟)
精读⑤。
4刷题纠错(15 分钟)
做⑦⑩,错题回⑥。
本课小目标学完你要能:① 说清四种隔离级别解决什么问题;② 区分脏读/不可重复读/幻读;③ 解释 MVCC。
② 一图看懂:事务与隔离全地图
读法:中心是事务 ACID,右隔离级别,下是 MVCC 与易错。
③ 本质直觉:并发事务像两个人同时改同一本账
三种读现象:① 脏读:读到别的事务还没提交的修改;② 不可重复读:同一事务内两次读同一行,值不一样(被别的事务改了);③ 幻读:同一事务内两次范围查询,行数变了(别的事务插入了新行)。
四种隔离级别:读未提交(啥都防不住)→ 读提交 RC(防脏读)→ 可重复读 RR(防脏读+不可重复读,InnoDB 默认)→ 串行化(全防,最慢)。
MVCC:每行存多个历史版本(undo log),读的时候按 ReadView 选一个可见版本,读写不互相阻塞——这就是 InnoDB 高并发的秘密。
不可重复读 vs 幻读不可重复读是同一行被 update(值变了);幻读是范围查询多了/少了行(insert/delete)。
④ 完整体系与对比表
四种隔离级别与现象
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| 读未提交 RU | 有 | 有 | 有 |
| 读提交 RC | 无 | 有 | 有 |
| 可重复读 RR | 无 | 无 | 有(标准)/InnoDB基本无 |
| 串行化 | 无 | 无 | 无 |
MVCC 原理
每行隐藏两列:trx_id(最后修改的事务 ID)、roll_pointer(指向 undo log 上的旧版本)。读时生成 ReadView,按规则判断哪个版本可见。这样读快照、写最新,读写不锁不阻塞。
RC vs RR 的 ReadViewRC 每次 SELECT 都生成新 ReadView(能看到别的已提交);RR 只在第一次 SELECT 生成(整个事务看到同一快照)
⑤ 用法场景与典型例题
例1(脏读)事务 A 改了余额未提交,事务 B 读到新值,A 又回滚,B 读到什么?
这是脏读。
B 读到了未提交的值,A 回滚后那值就不存在了。要读提交 RC 以上才能避免。
例2(不可重复读)RR 下事务内两次读同一行,中间别人改了并提交,结果?
RR 保证快照。
RR 下两次读看到的是同一快照版本,结果相同,避免了不可重复读。
例3(默认级别)MySQL InnoDB 默认隔离级别?
可重复读。
REPEATABLE READ。Oracle/PostgreSQL 默认 RC。
做题心法记现象:脏读=读未提交的脏数据;不可重复读=同行值变;幻读=行数变。级别逐级加锁/MVCC。
⑥ 高频错误诊断(4 条)
错误1:混淆不可重复读和幻读不可重复读针对 update(行值变);幻读针对 insert/delete(行数变)。
错误2:以为 RR 完全防幻读标准 RR 仍可能幻读;InnoDB 用间隙锁/Next-Key Lock 在很大程度上防住了。
错误3:以为隔离级别越高越好串行化并发差,按业务选。大多数互联网用 RC。
错误4:MVCC 是为了写更快MVCC 是让读写不阻塞、读不阻塞写,提升并发读。
⑦ 考点真题演练(4 题)
考点分布
| 考法 | 出题形式 | 应对 |
| 现象 | 脏读/不可重复/幻读 | 定义区分 |
| 隔离级别 | 对应防什么 | 背表 |
| 默认级别 | MySQL InnoDB | RR |
| MVCC | 读写不阻塞原理 | undo+ReadView |
真题基础1. 一个事务读到了另一个事务尚未提交的修改,叫?
真题中档2. MySQL InnoDB 默认的隔离级别是?
真题中档3. 同一事务内两次范围查询结果集行数不同,是因为别的事务插入了行,这叫?
真题拔高4. MVCC 实现读写不阻塞依赖?
⑧ 必背知识点卡
A 原子:全成或全败
C 一致:约束不破
I 隔离:并发互不干扰
D 持久:提交落盘
脏读:读未提交 RC 解决
不可重复:同行值被改 RR 解决
幻读:行数变了 串行化/间隙锁
MVCC:undo 多版本+ReadView 读写不阻塞
⑨ 应用输出:设计账户转账事务
场景:A 给 B 转账 100 元,要扣 A 加 B 同时成功或同时失败。
① 开启事务:begin。
② 扣 A:update account set balance=balance-100 where name='A'。
③ 加 B:update account set balance=balance+100 where name='B'。
④ 提交:两步都成功 commit;任一步失败 rollback,A 不会少钱。
⑤ 并发:默认 RR 下两个并发转账不会互相脏读;MVCC 保证读写不阻塞。
口述思路合上书说:"转账就是一个事务包两步 update,失败回滚,隔离级别默认 RR。"
⑩ 分层练习(基础 + 中档 + 拔高)
▍基础 6 题
基础1ACID 是什么?
原子、一致、隔离、持久。
基础3MySQL InnoDB 默认隔离级别?
可重复读 RR。
基础4不可重复读是什么?
事务内两次读同行值不同。
▍中档 6 题
中档7RC 能防脏读吗?
能,RC 只读已提交数据。
中档9undo log 在 MVCC 里干嘛?
存数据旧版本,供 ReadView 回溯。
中档10RC 和 RR 的 ReadView 区别?
RC 每条 select 新建;RR 第一次 select 建。
中档11串行化怎么防幻读?
事务排队执行,串行无并发。
中档12事务 ACID 里哪项由锁和 MVCC 保障?
隔离性 I。
▍拔高 6 题
拔高13Next-Key Lock 是什么?
行锁+间隙锁,锁住索引记录和间隙,防幻读。
拔高14什么是丢失更新?
两事务同时改一行互相覆盖,要用乐观锁/悲观锁。
拔高15乐观锁怎么实现?
加 version 字段,update where version=旧值。
拔高16MVCC 一定不用锁吗?
写操作仍加锁;读快照不加锁。
拔高17为什么互联网常用 RC 而不是 RR?
RC 并发更高,避免长事务快照 undo 链过长。
拔高18redo log 和 undo log 区别?
redo 保证持久性(先写日志),undo 保证原子性+MVCC 旧版本。
⑪ 记忆口诀 + 7 天复习计划
三句口诀① 原子一致隔离持久,隔离级别逐级防。② 脏读读未提交,不可重复同行变,幻读行数变。③ MVCC 多版本读写不阻塞,InnoDB 默认 RR。
| 天 | 任务 | 自检 |
| 第 1 天 | 读②③④,画隔离级别阶梯 | 现象对应对 |
| 第 2 天 | 背 ACID + 基础 1-6 | 三种现象分清 |
| 第 3 天 | 做中档 7-12,讲 ReadView | RC/RR 区别对 |
| 第 4 天 | 做拔高 13-18,讲 Next-Key Lock | 能讲清防幻读 |
| 第 5 天 | 做⑦真题 4 题 | 限时每题 2 分钟 |
| 第 6-7 天 | 合上书默写隔离级别表 | 不看资料全默对 |
← 返回软件技术总览