【WiredTiger 内核】Timestamps、Snapshot 与事务:可见性契约

💡 原文中文,约5300字,阅读约需13分钟。
📝

内容提要

本文介绍WiredTiger存储引擎的时间戳与快照机制。核心概念包括:应用时间戳由上层控制,执行时间是墙上时钟;active time window由oldest、stable、pinned界定可读与可丢弃历史;快照通过max/min/并发事务ID列表决定可见性;默认snapshot隔离,prepared事务有特殊边界。文章强调时间戳与快照共同支撑MongoDB的MVCC实现。

🔎

延伸解读

时间戳与执行时间分离的工程意义

WiredTiger 将应用时间戳与执行时间分离,使上层(如 MongoDB)能控制提交顺序,而非依赖墙上时钟。这种设计支持有限回绕(如 rollback to stable),但要求应用保证提交时间戳整体大于相关读时间戳,否则可能破坏一致性。理解这一契约有助于把握 MongoDB 全局时间与复制机制的底层约束。

active time window 的边界作用

active time window 由 oldest、stable、pinned 界定:oldest 限制新事务可读的最早时间,stable 区分已稳定与未稳定数据,pinned 则保护进行中的读,避免 oldest 推进过快导致历史被过早丢弃。这一机制直接决定了哪些历史版本可被安全 GC,是理解 WiredTiger 存储与清理策略的关键。

快照可见性检查的顺序依赖

快照可见性检查先比较 max/min 事务 ID,再查并发列表,顺序至关重要。max 边界排除创建后的事务,min 边界确保早期事务可见,并发列表则处理中间状态。这种设计在并发列表为空时也能高效判断,体现了 WiredTiger 对性能与正确性的平衡。

prepared 事务带来的特殊边界

prepared 事务引入 prepare 与 durable 时间戳,使读在 prepare 与 commit 之间返回冲突,在 commit 后 durable 前可能不安全。这要求应用层(如 MongoDB)负责避免不一致,也影响 checkpoint 与 History Store 的交互。理解这些边界有助于排查分布式事务中的一致性问题。

Q&A

WiredTiger中的应用时间戳和执行时间有什么区别?

应用时间戳是应用(如MongoDB)控制的时间点,用于表示事务的提交顺序,不一定等于墙上时钟;执行时间是事务实际发生的墙上时间。二者通常同向推进,但不必一一对应。

WiredTiger中active time window的边界是什么?

active time window由三个边界界定:oldest timestamp是应用允许新事务开始读取的最早应用时间;stable timestamp是已稳定与未稳定数据的分界,稳定侧数据固定且耐久;pinned timestamp是内部使用的下界,取min(oldest, 所有运行中事务的read timestamp),用于丢弃/GC历史。

WiredTiger的snapshot隔离级别下,快照是如何决定可见性的?

快照捕获创建时刻的全局事务状态,包含最大事务ID、并发事务ID列表和最小事务ID。可见性检查顺序为:事务ID大于等于max则不可见;小于min则可见;在并发列表中则不可见;否则可见。

WiredTiger中prepared事务的边界是什么?

prepared事务的prepare timestamp大于开始prepare时的stable,durable timestamp大于提交时的stable。prepare后commit前,读落在prepare与commit之间会返回WT_PREPARE_CONFLICT;commit后durable前,若stable已过commit但未到durable,读可能不安全,需应用负责避免不一致。

WiredTiger中pinned timestamp的作用是什么?

pinned timestamp是内部使用的下界,取min(oldest, 所有运行中事务的read timestamp),用于真正丢弃/GC历史的下界,避免应用推进oldest时伤及进行中的读。

WiredTiger中checkpoint与snapshot事务的关系是什么?

Checkpoint使用独立的特殊全局事务与快照。应用侧snapshot事务会把checkpoint的事务ID记为并发事务之一,从而忽略checkpoint尚未提交的元数据更改。

🏷️

标签

➡️

继续阅读