【WiredTiger 内核】History Store 与 Durable History(已迁入系列第 08 篇)

💡 原文中文,约10000字,阅读约需24分钟。
📝

内容提要

WiredTiger采用第三种MVCC方案:用户表B-Tree仅存最新已提交版本,旧版本存入全局History Store(WiredTigerHS.wt)。写路径通过reconciliation将旧版本写入HS,读路径按update chain→磁盘页→HS顺序查找。Durable History取代Lookaside,使历史可跨eviction/checkpoint持久查询,由minSnapshotHistoryWindowInSeconds控制保留窗口。与PostgreSQL堆版本、InnoDB undo相比,WT分离当前与历史,利于用户页驱逐,但增加历史I/O与磁盘开销。

🔎

延伸解读

历史存储的代价:读放大与磁盘开销

WiredTiger 将旧版本移入全局 History Store,用户表页可被驱逐,但读旧快照时需沿 update chain → 磁盘页 → History Store 的顺序查找,可能增加一次旁路 I/O。同时,文档更新常以整份旧 BSON 作为历史载荷存入 HS,即使只修改一个字段,也会导致磁盘空间随更新频率和大小增长。因此,评估存储需求时,不能只看 cacheSizeGB,还需考虑更新负载与历史保留窗口。

Durable History 与 Lookaside 的本质区别

MongoDB 4.4 用 History Store 取代 Lookaside,不仅是换文件名。Lookaside 更接近 cache overflow,重启后行为与可查询历史契约不同;而 History Store 是数据库目录中的正式表,旧版本在 reconcile 后仍可跨 eviction 和 checkpoint 被读取,前提是未被 oldest timestamp 或保留窗口回收。这使历史查询成为一等契约,但运维痛点从 LAS 无限膨胀转为 HS 体积与窗口参数的权衡。

与 PG/InnoDB 的故障模式差异

三种 MVCC 方案语义目标相近,但物理落点不同导致故障模式各异:PostgreSQL 表膨胀、InnoDB undo history 过长、WiredTiger 的 WiredTigerHS.wt 增长。WiredTiger 分离当前与历史,有利于用户页驱逐,但将读放大与历史 I/O 显式化。选型时需根据更新大小和频率评估磁盘,而非仅看缓存配置。

Q&A

WiredTiger 的 MVCC 实现与 PostgreSQL 和 InnoDB 有什么不同?

WiredTiger 采用第三种 MVCC 方案:用户表 B-Tree 只保存最新已提交版本,旧版本存入独立的全局 History Store(WiredTigerHS.wt)。PostgreSQL 在堆表中保留新旧元组,InnoDB 使用 undo log 保存旧版本。

WiredTiger 的 History Store 是什么?它存储在哪里?

History Store 是 WiredTiger 中用于存储旧版本数据的全局内部表,文件名为 WiredTigerHS.wt,位于 MongoDB 的 dbPath 目录下。所有用户表共享这一张历史表。

WiredTiger 中旧版本数据是如何写入 History Store 的?

当用户表页进行 reconciliation(通常由 eviction 或 checkpoint 触发)时,会检查 update chain,将最新已提交版本写入用户表磁盘页,将尚未过时的旧版本写入 History Store。具体由 __wt_hs_insert_updates 函数实现。

WiredTiger 中读操作如何找到旧版本数据?

读操作按顺序查找:先在内存 update chain 中查找,若没有则检查磁盘页上的版本,若仍不可见则进入 History Store,从该键的最新条目向更旧方向迭代,直到找到满足读时间戳和事务可见性的版本。

Durable History 与 Lookaside 有什么区别?

Durable History(History Store)是 MongoDB 4.4 起引入的,取代了 Lookaside(LAS)。LAS 主要作为 cache overflow 机制,在缓存不足时将内容溢出到磁盘;而 History Store 是持久化的历史版本表,用户表只保留最新版本,旧版本可跨 eviction 和 checkpoint 服务读操作,重启后依然可查询。

minSnapshotHistoryWindowInSeconds 参数的作用是什么?

该参数控制快照历史的保留窗口,即旧版本在 History Store 中保留的时间长度。窗口越大,可回溯的快照时间越长,但磁盘占用也越大。它从 MongoDB 5.0 起可用。

WiredTiger 的 History Store 如何回收空间?

History Store 通过 reconciliation 删除 globally visible tombstone 来回收空间。当 tombstone 的 stop timestamp 小于 oldest timestamp 且对并发事务全局可见时,checkpoint 可以删除包含这些记录的页,从而收缩 WiredTigerHS.wt 文件。

WiredTiger 的 History Store 与 InnoDB 的 undo log 相比有哪些优缺点?

WiredTiger 将当前版本与历史版本分离,有利于用户表页的 eviction,但增加了历史 I/O 和磁盘开销。InnoDB 的 undo log 在聚簇索引中保留当前行,通过 undo 链回溯旧版本,但 undo 膨胀可能拖慢 purge 和长事务。两者故障模式不同:PG 表膨胀、InnoDB undo history 过长、WT 的 WiredTigerHS.wt 与窗口参数。

🏷️

标签

➡️

继续阅读