【WiredTiger 内核】Checkpoint:跨文件一致快照
内容提要
本文介绍WiredTiger存储引擎的Checkpoint机制,作为崩溃恢复的已知时间点,与日志共同保证耐久性。流程包括加锁、eviction减压、准备、用户表reconcile、History Store(故意后置以包含新增写入)、落盘及元数据更新。通过generation防止eviction超前,支持并行checkpoint,并与Journal分工协作。
延伸解读
为何 History Store 必须后置
用户表 reconcile 过程中会向 History Store 追加写入,若先对 History Store 做 checkpoint,这些新增写入就会丢失。因此 WiredTiger 故意将 History Store 的 checkpoint 放在数据文件之后,确保 checkpoint 包含所有相关更新,从而保证一致快照的完整性。
generation 机制的作用
Checkpoint 开始时递增 generation,并标记已处理 btree 的 checkpoint_gen。若某 btree 的 generation 落后,可见性检查会纳入 checkpoint 事务 ID 或时间戳,阻止 eviction 将更新提前到 checkpoint 之前。这是并行 eviction 与 checkpoint 正确性的关键阀门。
并行 checkpoint 的边界
当 checkpoint_threads 大于 1 时,叶子页的 reconcile 可交给 worker 线程,但内部页仍由主线程处理。worker 使用独立 session 并导入主 checkpoint 快照副本。此外,跳过条件包括无修改、时间戳相等或空间不足,但可强制覆盖。
Q&A
WiredTiger的checkpoint是什么?它如何与日志共同保证耐久性?
Checkpoint是WiredTiger中崩溃或异常关机后可以恢复的已知时间点。它与日志(logging/journal)共同提供耐久性:恢复时从最近的checkpoint起步,再回放日志以覆盖checkpoint之间的修改。
WiredTiger执行checkpoint的主要步骤有哪些?
主要步骤包括:1) 加锁(获取checkpoint_lock等);2) 通过eviction减少脏页比例;3) 准备阶段(开始checkpoint事务、收集handle列表);4) 对用户表(data files)进行reconcile;5) 对History Store进行checkpoint(故意放在用户表之后);6) 将所有数据文件flush到磁盘;7) 更新元数据和turtle文件。
为什么WiredTiger在checkpoint时先处理用户表,再处理History Store?
因为用户表reconcile过程中可能会向History Store追加新的写入,如果先checkpoint History Store,就会漏掉这些新写入。所以故意将History Store的checkpoint放在用户表之后,以确保包含所有新增写入。
WiredTiger的checkpoint generation机制是如何防止eviction超前的?
Checkpoint开始时递增generation,处理完某个btree后将其checkpoint_gen设为最新。如果某btree的generation落后于当前checkpoint generation,可见性检查会纳入checkpoint事务ID/timestamp,从而阻止eviction将该树的更新赶到checkpoint前面。这保证了并行eviction与正在进行的checkpoint之间的正确性。
WiredTiger如何支持并行checkpoint?
通过设置checkpoint_threads > 1,主线程遍历树,叶子节点的reconcile可以交给worker线程处理,而内部页仍由主线程在排空done队列后处理。每个worker使用自己的session,并导入主checkpoint快照的副本。
WiredTiger在checkpoint时如何跳过某些btree?
如果btree自上次checkpoint以来没有修改、上次checkpoint timestamp已等于当前stable timestamp,或文件尾无可用空间等,可以跳过该btree的checkpoint。这些条件可以通过强制配置覆盖。
WiredTiger的checkpoint与journal的分工是什么?
Checkpoint钉住一个已知的好点(一致快照),而checkpoint之间的修改由journal/logging覆盖。崩溃恢复时,从最近的checkpoint开始,再回放日志以恢复checkpoint之后的所有修改。