{T}

事务与恢复

0. 引言

事务的 ACID 中,原子性要求事务要么全部生效要么全部不生效,持久性要求一旦提交结果永久可见——崩溃恢复机制正是为实现这两点而存在。本文从单机存储的 WAL 与恢复策略讲起,经过隔离级别与并发控制,最后上升到分布式事务的原子提交协议与两种代表性路线(Spanner 与 Calvin)。

1. 本地恢复:WAL 与检查点

1.1 预写日志(WAL)

WAL 的核心原则:对数据的任何修改,必须先写入日志并落盘,再修改内存中的页

code
写入流程:
1. 将修改记录追加到 WAL,fsync 落盘
2. 在内存中应用修改(脏页)
3. 脏页由后台异步刷盘

崩溃后,数据库重放(Replay)WAL 中已提交的事务,撤销(Undo)未提交的事务,从而恢复到一致状态。

1.2 检查点(Checkpoint)

若每次恢复都从头重放全部 WAL,恢复时间会随日志增长而变长。检查点机制定期将内存中的脏页刷盘,并记录"已持久化到何处",恢复时只需从最近检查点之后的日志开始重放。

1.3 缓冲与刷盘策略

策略行为权衡
Force事务提交时强制刷盘所有脏页恢复快但写入慢
No-Force依赖 WAL,提交时只保证 WAL 落盘,脏页异步刷写入快
Steal / No-Steal未提交事务的脏页是否允许提前刷盘影响 Undo 日志的设计

现代系统普遍采用 No-Force + Steal + WAL,兼顾性能与可恢复性。

2. 隔离级别与并发控制

2.1 四级隔离

隔离级别脏读不可重复读幻读
读未提交(RU)可能可能可能
读已提交(RC)可能可能
可重复读(RR)可能
串行化(Serializable)

2.2 三种并发控制机制

机制原理优点缺点
两阶段锁(2PL)事务分为加锁与解锁两阶段,不交叉可实现串行化读写互斥,易死锁,需死锁检测/超时回滚
多版本并发控制(MVCC)每次写生成新版本,读基于快照访问特定版本读不加锁,读多场景性能好需维护多版本与垃圾回收(Vacuum)
乐观并发控制(OCC)执行时不加锁,提交时校验冲突,冲突则回滚重试低争用下吞吐高高争用下大量回滚

2.3 分布式下的并发控制

跨节点的并发控制需结合全局事务与复制:

  • 通过原子提交协议保证跨节点原子性(见第 3 节);
  • 通过全局时间戳共识算法确定全局有序的提交顺序——如 Spanner 的 TrueTime、Calvin 的全局排序。

3. 分布式原子提交协议

3.1 两阶段提交(2PC)

2PC 是最经典的原子提交协议,引入协调者(Coordinator)统一决策:

图表渲染中…
  • 阶段一(Prepare):协调者向所有参与者发送 Prepare;参与者写 Undo/Redo 日志、锁定资源,回复 Yes/No;
  • 阶段二(Commit):全部 Yes → 协调者发 Commit,参与者提交并释放锁;任一 No → 协调者发 Rollback,参与者回滚。

缺点阻塞——协调者故障后参与者持有锁等待;单点——协调者是瓶颈与单点。

3.2 三阶段提交(3PC)

在 2PC 的准备与提交间增加**预提交(Pre-Commit)**阶段,并引入超时机制:

  • 优点:参与者超时后可自主决策,减少无限阻塞;
  • 缺点:网络分区下仍可能不一致,实现复杂,实践中少用。

3.3 基于 Paxos 的原子提交

将提交决策本身放入共识:协调者的决策通过 Paxos / Raft 复制,即使协调者崩溃,新协调者也能从已复制的日志恢复决策,避免 2PC 的阻塞单点。代表如 Spanner 用 Paxos 复制事务状态;关键点:提交记录一旦在多数派达成,即不可逆。

本地与分布式的关系:参与者的准备阶段依赖 WAL——写日志落盘后再回复 Yes,保证崩溃后可重放决策。

4. 两条分布式事务路线:Spanner 与 Calvin

4.1 Spanner:TrueTime + 2PC

Spanner 是 Google 的全球分布式数据库,通过以下组合实现外部一致(线性一致)的分布式事务:

  • TrueTime API:基于 GPS + 原子钟提供带有不确定区间的时间戳 TT(now) = [earliest, latest]
  • 提交时间戳:协调者选择 timestamp > 已见最大 TT.now().latest,保证事务顺序与真实时间一致;
  • 2PC + Paxos:每个分片的副本通过 Paxos 复制,2PC 在分片间提交。

特点:线性一致的跨节点事务,但依赖专用硬件(原子钟)校准时钟。

4.2 Calvin:确定性调度

Calvin 走另一条路——在事务执行前,先通过共识就事务的全局顺序达成一致,再确定性地顺序执行

  • 全局顺序:所有节点按同一顺序执行事务日志;
  • 确定性执行:相同输入 + 相同顺序 → 相同结果,无需在执行时协调;
  • 优势:避免 2PC 的运行时交互,吞吐高;
  • 局限:需预先确定事务(只读事务需特殊处理),不适合高度交互式负载。

4.3 对比

维度SpannerCalvin
顺序来源TrueTime 真实时钟共识确定的逻辑顺序
执行方式并发 + 锁 + 2PC确定性顺序执行
一致性外部一致(线性)串行化
硬件依赖原子钟 / GPS
适用地理分布、强一致高吞吐、可预测事务

5. 小结

  • 本地恢复三件套:WAL(先日志后数据)+ 检查点(缩短恢复)+ No-Force/Steal(性能与可恢复性兼得);
  • 并发控制:2PL(强一致易死锁)、MVCC(读不阻塞)、OCC(低争用高效);
  • 分布式原子提交演进:2PC(阻塞/单点)→ 3PC(超时自决策)→ Paxos 化(决策复制,不阻塞);
  • 两条路线:Spanner 用真实时钟排序 + 2PC/Paxos,Calvin 用确定性顺序执行避免运行时协调。

下一章讲解分布式协调:共识算法、领导者选举与协调服务。