数据库事务、并发与恢复总览
把事务、ACID、隔离级别、并发异常、MVCC、锁与 Undo/Redo/WAL 放在一张图里理解,作为数据库事务体系的总览心智模型。
[!info] related notes
数据库事务、并发与恢复总览
[!abstract] 核心主线 Transaction 定义一个提交边界;ACID 描述它希望提供的性质;Isolation Level 规定并发事务允许观察到什么;MVCC 与 Lock 协作实现可见性和冲突控制;Undo / Redo / WAL 支撑回滚、持久化和崩溃恢复。
一张图看完整关系
Transaction Boundary
├─ Atomicity → rollback / undo / transaction state
├─ Consistency → constraints + application invariants
├─ Isolation → visibility + conflict control
│ ├─ MVCC snapshots
│ └─ locks / serialization checks
└─ Durability → WAL / redo + fsync + recovery
ACID 各自回答什么
Atomicity
事务中的写要么全部提交,要么在 Abort / Crash 后不留下半完成的逻辑结果。Undo、版本和恢复协议常参与实现。
Consistency
事务前后应满足数据库约束与业务不变量。数据库可以强制 Unique、Foreign Key、Check 等规则;跨表或跨服务业务规则仍需要正确事务边界和应用设计。
Isolation
并发事务的中间状态不会以超出所选隔离级别的方式互相干扰。
Durability
COMMIT 成功后,即使进程或机器故障,系统也能通过持久日志和恢复重建已提交结果。
常见并发现象
| 现象 | 含义 |
|---|---|
| Dirty Read | 读到其他事务尚未提交的写 |
| Non-repeatable Read | 同一行两次读取结果变化 |
| Phantom | 同一谓词两次读取,匹配行集合变化 |
| Lost Update | 两个事务基于旧值写入,一方结果被覆盖 |
| Write Skew | 各自修改不同记录,却共同破坏跨记录不变量 |
只背前三种不足以分析真实并发;Lost Update 和 Write Skew 在业务系统中非常常见。
四个标准隔离级别
| Level | 直觉 | 不能仅凭名称假设 |
|---|---|---|
| Read Uncommitted | 允许最弱可见性 | 具体引擎可能仍不提供 Dirty Read |
| Read Committed | 每条语句看到已提交快照 | 同一事务两次读可变化 |
| Repeatable Read | 事务内普通快照读通常稳定 | 不同数据库对 Phantom / Write Conflict 处理不同 |
| Serializable | 结果等价于某个串行顺序 | 可能通过锁或 Serializable Snapshot + Abort 实现 |
SQL 标准名称描述现象下限,具体实现必须看数据库文档和实验。
MVCC 的核心模型
logical row
→ version created by transaction X
→ previous version
→ previous version ...
snapshot / read view
→ decide which version is visible
MVCC 让普通一致性读在很多情况下不必阻塞写入,也让不同隔离级别选择不同 Snapshot 生命周期。
Read Committed
通常每条语句建立新的已提交 Snapshot,因此同一事务后续语句可能看到其他事务的新提交。
Repeatable Read
通常事务内复用较稳定的 Snapshot,因此普通读取保持一致视图。具体 Snapshot 建立时机和锁定读行为按数据库实现。
MVCC 不会消灭锁
锁仍用于:
- 同一行的并发写冲突;
SELECT ... FOR UPDATE等锁定读;- DDL / Metadata;
- Unique / Foreign Key 维护;
- Range / Predicate Protection;
- Serializable 实现的一部分。
MVCC → choose visible committed version for reads
Locks / Validation → coordinate conflicting writes and invariants
Snapshot Read 与 Current / Locking Read
Snapshot Read
读取 Snapshot 可见的历史版本,不一定等待最新写事务。
Current / Locking Read
读取较新的可操作版本并加锁,例如:
SELECT ... FOR UPDATE;
UPDATE ...;
DELETE ...;
所以同一事务中普通 SELECT 与 SELECT FOR UPDATE 可能观察不同时间语义。
Phantom 为什么容易讲乱
Phantom 不是“读到新版本的一行”这么简单,而是某个谓词匹配的集合发生变化:
WHERE amount > 100
不同数据库通过 Snapshot、Range / Gap Lock、Predicate Lock 或 Serializable Conflict Detection 处理。以 InnoDB 为例,Repeatable Read 的普通 Snapshot Read 通常保持一致视图;锁定范围读和写入还会使用 Next-key / Gap Lock 等机制。不能把一种引擎实现推广为所有数据库规则。
写冲突与业务更新
典型 Lost Update:
T1 reads balance=100
T2 reads balance=100
T1 writes 90
T2 writes 80
治理方式:
- 原子
UPDATE balance = balance - ?; SELECT FOR UPDATE;- Optimistic Version Column;
- Serializable Transaction;
- Unique / Check Constraint。
选择取决于冲突率、等待成本和业务不变量。
Undo、Redo、WAL 与 Binlog
| 机制 | 主要职责 |
|---|---|
| Undo | 回滚未提交修改、为 MVCC 提供旧版本(具体实现依引擎) |
| Redo | 重做已提交但 Data Page 尚未落盘的修改 |
| WAL | 先写日志后写数据页的持久化原则/日志体系 |
| Binlog | MySQL Server 层逻辑变更日志,常用于复制、CDC、恢复 |
术语在不同数据库中不完全一一对应。稳定理解是:
before data page flush
→ durable log describes change
→ crash recovery replays committed work
→ uncommitted work is ignored or undone
COMMIT 时发生什么
高层流程:
validate constraints / conflicts
→ append commit-related log records
→ make required log durable
→ mark transaction committed
→ release / transfer locks
→ data pages may flush later
具体 Group Commit、fsync、Replication ACK 和 Durability 配置会改变延迟与数据丢失窗口。
长事务的代价
- 持有锁更久;
- 保留旧版本,阻碍 Vacuum / Purge;
- Undo / WAL 增长;
- Replica Lag / Recovery 增加;
- 连接池被占用;
- 冲突和 Abort 概率上升。
事务应围绕最小业务原子边界,不在事务内等待用户输入、长时间网络调用或模型生成。
一条排障路径
symptom: slow / blocked / inconsistent
→ inspect active transactions and age
→ lock waits / deadlocks
→ isolation level and query type
→ execution plan / rows touched
→ long snapshots / version cleanup
→ WAL / fsync / replication
→ application retry / idempotency
面试一分钟回答
事务定义一组操作的提交边界,ACID 描述原子性、一致性、隔离性和持久性。隔离级别规定并发事务允许观察到什么,MVCC 通过版本和 Snapshot 支持一致性读,锁与冲突检测负责写写冲突、锁定读和业务不变量。提交时通常先保证 WAL/Redo 持久,再允许 Data Page 以后刷盘;Undo 用于回滚和旧版本。具体 Read Committed、Repeatable Read、Phantom 和 Serializable 行为要按数据库实现分析。
掌握标准
- ACID 四个性质与实现机制不混淆;
- Dirty / Non-repeatable / Phantom / Lost Update / Write Skew;
- RC 与 RR 的 Snapshot 生命周期;
- MVCC 与 Lock 的协作边界;
- Snapshot Read 与 Locking Read;
- Undo / Redo / WAL / Binlog 的职责;
- 能分析长事务、锁等待和崩溃恢复。