TL;DR(30 秒扫完)
- ACID 四个字母,前三个(A/I/D)由数据库保证,C 靠数据库+业务一起保证
- 三个日志 各司其职:
undo记旧值做回滚、redo记物理页做崩溃恢复、binlog记逻辑操作做复制 - 隔离级别 靠 MVCC + 锁配合实现,MySQL 默认 RR,互联网公司常切 RC
- 2PC 是保证 redo 和 binlog 一致的协议,三阶段:
redo prepare → 写 binlog → redo commit - 一个事务的完整提交流程 = WAL 写 redo → 2PC 协调 → binlog 落盘 → InnoDB commit → 通知主线程
关键结论
结论 AACID 的 C 不是数据库单独提供的,是业务和数据库共同保证
结论 B持久性靠 redo log 的 WAL 机制,不是 binlog
结论 CMySQL 内部 2PC 的核心不变量是"binlog 是提交成功的标志"
结论 DMVCC 只用于快照读,当前读(SELECT FOR UPDATE / UPDATE / DELETE)不走 MVCC
结论 EMySQL 默认 RR 不是"性能优先",而是一致性优先的折中
完整讲解(费曼四步)
STEP 1 · 概念
MySQL 事务的核心是"让多个读写操作要么全部成功,要么全部回滚,且不干扰其他事务,且已提交的结果不丢"。这套机制由三块拼起来:日志层(undo/redo/binlog)+ 隔离机制(锁 + MVCC)+ 协调协议(2PC)。STEP 2 · 大白话
图书馆比喻:- undo log 是"修改记录本"——每次改书前抄一份原文,出问题按记录本恢复
- redo log 是"施工日志"——记着哪本书哪页要改成什么,崩溃后用日志重放
- binlog 是"借阅流水"——记着每次操作是谁做的,供另一个图书馆(从库)照抄
- 2PC 是"图书馆经理和分馆的确认流程"——总馆说"改好了",分馆说"记好了",两边都对上才算真完成
STEP 3 · 底层
三个日志的分工
| 日志 | 层级 | 记录内容 | 主要用途 |
|---|---|---|---|
| undo log | InnoDB 引擎层 | 旧值(逻辑) | 回滚 + MVCC |
| redo log | InnoDB 引擎层 | 物理页修改 | 崩溃恢复(WAL) |
| binlog | MySQL Server 层 | 逻辑 SQL / row | 主从复制 + 灾备 |
ACID 每个字母对应机制
| 字母 | 含义 | 核心机制 |
|---|---|---|
| A | 原子性 | undo log(回滚) |
| C | 一致性 | 约束 + 业务代码 + 前三性 |
| I | 隔离性 | 锁(行锁/间隙锁)+ MVCC |
| D | 持久性 | redo log + 2PC |
隔离级别谱系
RU → RC → RR → Serializable
↑ ↑
Oracle 默认
默认 MySQL 默认
- RC:每次 SELECT 新建 ReadView,只有行锁,无间隙锁
- RR:事务首次 SELECT 生成一次 ReadView,next-key lock
MySQL 2PC 三阶段
Phase 1: redo prepare(不 commit)
Phase 2: 写 binlog 到磁盘
Phase 3: redo commit
崩溃恢复判断表:
| redo 状态 | binlog 状态 | 处理 |
|---|---|---|
| prepare | 未写 | 回滚 |
| prepare | 已写 | 提交 |
| commit | 已写 | 已完成,重放 |
关键参数
innodb_flush_log_at_trx_commit = 1 # 每次 commit 刷 redo(最安全)
sync_binlog = 1 # 每次刷 binlog
innodb_deadlock_detect = ON # 自动死锁检测
innodb_lock_wait_timeout = 50 # 锁等待超时(秒)
STEP 4 · 简化
一句话总结:ACID 靠三日志撑起来——A 靠 undo、D 靠 redo + 2PC、I 靠锁+MVCC、C 靠业务。binlog 是复制用的,不是持久性用的,这是最容易混的点。 记忆口诀:- 日志三兄弟:undo 撤销 · redo 重做 · binlog 复制
- 2PC 三阶段:prepare · binlog · commit
- 隔离级别:RC 每次新 ReadView,RR 只生成一次
常见误区
把 undo log 说成"重做日志"
undo = 撤销,redo = 重做
说"binlog 保证持久性"
持久性靠 redo log(WAL),binlog 只负责复制
说"MySQL 2PC 是先写日志再批量提交到磁盘"
那是组提交,不是 2PC
说"RR 是为了性能优先"
RR 是一致性优先的折中,RC 才更省锁
说"MVCC 用于所有读"
MVCC 只用于快照读,当前读走锁
ACID 的 I 答成"可用性"
I = Isolation(隔离性)
延伸追问
redo log 和 binlog 都是"日志",为什么不能只用一个?
redo 是引擎层物理日志,服务崩溃恢复;binlog 是 Server 层逻辑日志,服务复制。分工不同,缺一不可。
2PC 崩溃后如何决定提交还是回滚?
看 redo 状态和 binlog 状态:binlog 未写则回滚,binlog 已写则提交。
innodb_flush_log_at_trx_commit=2 什么时候用?MySQL 崩溃不丢(已写 OS cache),系统崩溃可能丢。适合日志量大、可容忍系统崩溃丢数据的场景。
为什么很多互联网公司切 RC?
RR 的间隙锁死锁多、锁等待长;RC 锁粒度小并发高。
速查表
ACID: A→undo / C→业务 / I→锁+MVCC / D→redo+2PC
日志: undo撤销 · redo重做 · binlog复制
2PC: prepare → binlog → commit
崩溃: 无binlog→回滚 / 有binlog→提交
RR: 一次 ReadView · 有间隙锁
RC: 每次 ReadView · 无间隙锁
双1: sync_binlog=1 + innodb_flush_log_at_trx_commit=1
Anki 候选卡片
Q: ACID 每个字母对应什么机制?
A: A→undo / C→业务+约束 / I→锁+MVCC / D→redo+2PC
Q: undo log 和 redo log 分别做什么?
A: undo 记旧值做回滚和 MVCC;redo 记物理页修改做崩溃恢复
Q: binlog 的主要用途?
A: 主从复制 + 灾备,不是持久性保证
Q: 2PC 三阶段是什么?
A: redo prepare → 写 binlog → redo commit
Q: 2PC 崩溃恢复判断逻辑?
A: binlog 未写→回滚;binlog 已写→提交
Q: RC 和 RR 在 ReadView 上的差异?
A: RC 每次 SELECT 新建;RR 事务首次 SELECT 生成一次
Q: MVCC 用于哪种读?
A: 快照读;当前读(SELECT FOR UPDATE / UPDATE / DELETE)走锁
Q: MySQL 默认 RR 的原因?
A: 一致性优先的折中——MVCC 让 RR 快照读不加锁,性能仍高
关联题目
- ⚠️ 《什么是事务的 ACID 特性》— Round 1 Q1, ⭐⭐(I 答成可用性)
- ⚠️ 《MySQL 事务 ACID 是如何实现的?》— Round 2 B2, ⭐⭐(undo/redo 混淆)
- ⚠️ 《MySQL 中的事务隔离级别?》— Round 2 B1, ⭐⭐⭐(RC/RR 边界)
- ⚠️ 《为什么 MySQL 默认使用 RR 隔离级别?》— Round 2 B4, ⭐(方向反了)
- ⚠️ 《什么是事务的 2 阶段提交?》— Round 2 B5, ⭐⭐(混淆组提交)
- ⚠️ 《介绍下 MySQL 5.7 中的组提交?》— Round 1 Q8, ⭐⭐(术语错误)
关联知识
ACID 靠三日志(redo/undo/binlog)+ MVCC+锁 + 2PC 撑起来
图书馆:undo 是修改记录本,redo 是施工日志,binlog 是借阅流水
✦ 记 忆 口 诀 ✦
日志三兄弟:undo 撤销 · redo 重做 · binlog 复制
关键可视化
ACID 每个字母对应机制
flowchart TB A["ACID 四大特性"] A --> A1["A 原子性"] A --> C1["C 一致性"] A --> I1["I 隔离性"] A --> D1["D 持久性"] A1 --> A2["undo log 回滚"] C1 --> C2["约束 + 业务代码"] I1 --> I2["锁 + MVCC"] D1 --> D2["redo log + 2PC"]
MySQL 内部 2PC 三阶段
flowchart LR S["事务开始"] --> P1["Phase 1: redo prepare"] P1 --> P2["Phase 2: 写 binlog"] P2 --> P3["Phase 3: redo commit"] P3 --> E["事务提交完成"] P1 -->|崩溃| C1["判断 binlog 是否已写"] P2 -->|崩溃| C1 C1 -->|未写| R["回滚"] C1 -->|已写| T["提交"]
隔离级别谱系
flowchart LR RU["RU"] --> RC["RC<br/>每次新 ReadView"] RC --> RR["RR<br/>首次 ReadView<br/>默认"] RR --> SER["Serializable"]
费曼式可视化(完整图解)
↗ 新窗口打开知识关系
⬆️ 前置(Prerequisite)
暂无🔄 延伸(Extends)
mvcc⚡ 对比(Contrast)
MVCC 快照读— MVCC 是 ACID 中 'I 隔离性' 的实现方案之一redo vs undo log— 最容易混:redo=重做物理页;undo=撤销旧值;两者不同层级
🎯 概念
📏 规则
⚠️ 误区
🔍 追问
✨ 口诀
共 0 张卡,点击翻面