第 7 篇 区分 stable 与 unstable 时间窗;第 10 篇 说明 logged 表可用 WAL 做 commit 级耐久。对带时间戳、依赖 stable 语义的表,启动恢复、关闭或应用显式调用时,WiredTiger 跑 Rollback to Stable(RTS):只保留被视为 stable 的修改。Architecture Guide Rollback to Stable 是本篇主来源。
本文是「WiredTiger 内核」系列第 11 篇(共 17 篇)。→ 系列目录
先修:第 7–10 篇;第 08 篇。续读:第 14–15 篇。
版本锚定:Architecture Guide Version 12.0.0 /
developRollback to Stable;源码mongodb-8.0的src/rollback_to_stable/。
一、何谓 unstable
修改被视为 unstable,若:
- 其 durable timestamp 大于 stable timestamp;或
- 其事务 ID 按 recovery checkpoint snapshot(每次 checkpoint 结束时保存的快照信息)判定为未提交。
RTS 扫描库中表,去掉不稳定修改。运行时需要独占数据库,不允许并发事务。
触发:startup、shutdown,或应用发起(含 dry-run)。Connection 打开流程末尾也会跑 RTS(第 2 篇)。
二、选哪些表、跳过哪些表
选中(满足之一即可):
- 表已修改;
- 有 prepared updates;
- 有事务 ID 超出 recovery checkpoint snapshot 的更新(仅重启阶段);
- checkpoint 的 durable start/stop 时间戳大于 stable。
可能跳过(非穷尽):空表;有时间戳更新但未设 stable;文件缺失/损坏;元数据专用;logged 表(commit 级耐久,不必 RTS);无 aggregated time window 的旧版表(Guide:主要见于 MongoDB 4.4 前)等。
三、对选中表做什么
页读入 cache 后:
- 去掉不稳定的内存更新与 HS 中的不稳定历史;
- 不稳定的 on-disk 版本:若有稳定的内存更新则替换为它,否则取 HS 中最新稳定版本;若两者皆无,删除该数据项;
- 若表没有时间戳更新:删掉该表在 HS 中的全部历史,保留 on-disk 值。
Guide History Store 同口径:RTS 按 stable 找仍稳定的版本写回用户表,并删不稳定 HS 条目。
中止不稳定更新的手法(摘要)
- 内存链:从新到旧 abort,直到碰到稳定更新;要删键时在链上挂全局可见 tombstone,稍后 reconcile 去掉。
- On-disk:start 不稳定且链上无稳定更新 → 查 HS;HS 也无 → 删键。若存在 stop 且 stop 不稳定 → 把 on-disk 更新恢复进 update list(例 3)。
Guide 给了三则例子(稳定 ts=10/20/30),此处不逐行抄写数值表;读原文 Examples 1–3 可与上列规则对照。
少读页
用页上 time aggregate 与 stable / recovery snapshot 比较,跳过无需处理的页;不对 internal 页跑 RTS 更新逻辑(无更新),但仍读入以导航到 leaf。
四、与 HS、时间戳、事务 ID
- HS 删除:用标准 HS cursor,从最高 start timestamp 向旧删到 rollback 时间戳为止;也可能把稳定版本读回数据表。
- RTS 结束后把全局 durable timestamp 回卷到 stable(若已无不稳定更新,定义上允许)。
- HS 中可能出现 start==stop、prepared
回滚残留、
WT_TS_MAXstop 夹在中间等非直觉形态;RTS 有专门校验与忽略排序特例,随后由 reconcile 清理(Guide Interaction with timestamps)。 - 处理过的更新会 清除事务 ID:恢复后 write generation 重置,残留「合法」txn ID 会导致新快照误判不可见。
五、与 Checkpoint / Eviction
- RTS 运行期间不能做 checkpoint(持 checkpoint 锁;系统须静止)。
- RTS 完成后通常再做一次 checkpoint,使内存与磁盘一致(可配置跳过)。
- Eviction 无特殊旁路:RTS 会产生大量 clean/dirty 页,带来 cache 与写 I/O 压力;trigger/target 规则仍适用。
Dry-run:走同一套访问路径但不改数据/HS;仍需独占锁;统计项只反映「访问了什么」,不反映「中止了多少」。
单表
RTS(rollback_to_stable_one):供
salvage 等场景,避免全库扫描。
六、开放问题(系列后部)
- 复制延迟导致 stable/oldest 推进缓慢时,RTS 在启停路径上的耗时与 HS 体量如何耦合(第 14–15 篇)。
- Prepared 与 durable/stable 交错窗口(第 7 篇)在 MongoDB 层如何收束——本篇只钉 WT 契约。
本篇无本地 RTS dry-run 实测。
七、收束
- RTS = 按 durable/stable 与 recovery snapshot 去掉不稳定修改;常读 HS 写回用户表。
- Logged 表可跳过;需独占;完成后常 checkpoint。
- 磁盘形态篇从第 12 篇开始:Block manager、页格式与压缩。
参考资料
- WiredTiger Architecture Guide, Rollback to Stable:https://source.wiredtiger.com/develop/arch-rts.html
- Timestamps、History Store、Checkpoint
mongodb-8.0:src/rollback_to_stable/- 第 7–8、10 篇;系列索引
上一篇:Journal
/ Logging
下一篇:Block
manager、页格式与压缩
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【WiredTiger 内核】文档库存储引擎全景:MongoDB 默认引擎的生态位
定位文档库默认引擎 WiredTiger 相对 PG/InnoDB/SQLite/RocksDB 的生态位;钉住 Session→Cache→Reconcile→HS→Checkpoint 主线、站内分工与 17 篇阅读路线,并以 Berenson 隔离词汇与 Durable History 为学术/工程锚点。
【WiredTiger 内核】Eviction:脏页必须先 reconcile
拆解 WiredTiger Eviction 的 server/worker/队列、target/trigger 阈值,以及 dirty eviction 经 reconciliation 把最新值写入用户表、旧版本写入 History Store;说明应用线程被迫协助驱逐的条件。
【WiredTiger 内核】Reconciliation:内存页到 on-disk image
拆解 WiredTiger reconciliation:把 in-memory 页转为 on-disk image、按 leaf_page_max 与 split_pct 分裂,并在用户表 reconcile 时选出最新已提交值、将更旧更新写入 History Store;锚定 wiki 与 src/reconcile/。
【WiredTiger 内核】Timestamps、Snapshot 与事务:可见性契约
拆解 WiredTiger 应用时间戳(oldest/stable/pinned)、事务 read/commit timestamp、快照隔离下的可见性检查,以及 prepared 的 prepare/durable 边界;为 History Store 与 Rollback-to-Stable 提供时间轴。