标题: ‘chDB Durable’
侧边栏标题: ‘概述’
slug: /durable
描述: ‘chDB Durable 如何使嵌入式 chDB 数据库能从对象存储中恢复’
关键词: [‘chdb’, ‘durable’, ‘对象存储’, ‘备份’, ‘wal’, ‘检查点’]
文档类型: ‘指南’

chDB Durable 使得嵌入式 chDB 数据库能够在进程重启、机器迁移和临时任务之间进行恢复。

不是一个远程数据库,也不是 chDB 数据目录的实时副本。查询和写入仍然在本地 chDB 进程中运行。对象存储保存的是通过最后一次成功的 flush()checkpoint() 操作后的可恢复状态:一个完整的检查点(checkpoint)后跟一个语句 WAL。

关于跨绑定的契约,请参阅 Durable V1 协议。关于用例和 Python 示例,请参阅 durable agent memory cookbook

工作原理 {#how-it-works}

Python / Node.js / Go / Rust 绑定

应用程序

语言绑定 API

Durable 控制平面

对象存储提供者

引擎适配器

chdb-core C ABI

本地热数据库
和私有临时路径

对象存储

head.json

不可变 WAL 段

不可变完整检查点

该设计包含三个层级:

  • chdb-core 负责运行查询,并提供用于查询分析、数据库备份和恢复的 C ABI。
  • 语言绑定 负责处理存储提供者、凭证、WAL 缓冲、检查点编排、租约(lease)、CAS、隔离(fencing)、重试和资源清理。
  • V1 协议 定义了对象布局、head.json、WAL 格式、状态转换、错误类别以及每个绑定共享的行为。

对象存储保存恢复状态。本地 MergeTree 数据目录仍然是热工作副本。

持久化边界 {#durability-boundaries}

操作结果
query()运行一个只读语句;不会向 WAL 添加任何内容。
execute()在本地运行一个变更操作,并将其追加到内存中的 WAL 缓冲区;此时尚未持久化。
flush()上传一个 WAL 段,并通过 CAS 将其提交到 head.json;成功即建立一个持久化边界。
checkpoint()创建完整的数据库备份,将其发布为新的基础,并清空清单中的 WAL 列表。
open()读取 head,恢复基础备份,然后按顺序重放 WAL 段。
close()停止新操作,执行 flush,释放租约,并清理本地资源。

如果应用程序承诺一个成功的请求能在另一台机器上恢复,它必须在返回成功之前等待 flush()

一致性与故障 {#consistency}

V1 是一个单写入者协议。写入者通过原子比较并交换(compare-and-swap)在 head.json 中获取租约。租约代次(generation)和 ETag 隔离机制(fencing)会阻止陈旧的写入者。只读开启者不获取租约。

检查点和 WAL 段使用唯一的、不可变的键。只有 head.json 是可变的,因此一次成功的上传后若 head CAS 失败,则之前的恢复状态保持不变。

存储超时并不能证明写入失败;提供者可能在响应丢失前已提交了它。绑定会重新读取对象,并检查键、序列、大小、SHA-256 摘要和租约所有权。如果它仍然无法证明结果,将返回 commit_ambiguous,而不是报告成功。

升级兼容性 {#upgrade-compatibility}

Durable V1 做出了三个独立的向后兼容性承诺:

  • C ABI: 后续的 chdb-core 版本会保持已发布符号、签名和语义不变。结构体仅在末尾增加,现有的枚举和标志值不会被重新编号。这使得来自不同版本的头文件和 libchdb 能够安全地进行协商。
  • 备份存档: 后续的 chdb-core 版本能够恢复由早期版本创建的 V1 完整备份。如果存档格式必须破坏兼容性,核心会递增 backup_format,而不是让 RESTORE 意外失败。
  • Durable 协议: 后续的绑定将继续读取 V1 对象,并保留已冻结字段和状态转换的含义。新需求会使用协议版本或命名特性,因此较旧的读取器可以在遇到不兼容时安全地报错关闭。

这些承诺是分别指定和测试的。一个新版本必须支持旧的 ABI、旧的完整备份和旧的 Durable 对象。反向则不保证:较旧的版本不一定需要理解未来的格式或特性。

绑定不要求 head.engine.version 与正在运行的引擎完全匹配。它们使用显式的兼容性字段:

backup_format > reader baseline   -> engine_incompatible
running_version < min_reader      -> engine_incompatible
otherwise                         -> open

V1 能力 {#v1-capabilities}

  • 每个 Durable 对象对应一个 chDB 数据库。
  • 一个写入者和任意数量的只读开启者。
  • 支持语句 WAL 重放的完整检查点。
  • 支持 S3 和其他支持原子条件创建和替换的对象存储。
  • 对检查点和 WAL 段进行大小和 SHA-256 验证。
  • 基于 backup_formatmin_reader 的引擎兼容性检查。
  • 跨语言绑定的共享对象格式和错误模型。

V1 边界 {#v1-boundaries}

V1 不支持:

  • 增量检查点;
  • Parquet 或数据 WAL;
  • 多个写入者、每个对象多个数据库,或跨对象事务;
  • 数据库外部的全局状态,包括 UDF、访问实体和命名集合;
  • 针对选定表、分区或时间范围的备份;
  • 远程垃圾回收、对象销毁、旧引擎读取新存档,或跨备份格式的迁移。

语句 WAL 在恢复期间会重新执行 SQL。使用 now()rand()、可变外部数据或类似非确定性输入的变更操作,在重放时可能会产生不同的结果。请将这些值物化为 SQL 字面量,或在操作后执行检查点。

V1 使用的 chdb-core 生命周期允许每个进程有一条活跃的数据路径。一个进程不能同时打开具有不同临时路径的 Durable 对象;如需并行,请使用单独的进程。

汇总与保留 {#rollup-and-retention}

Durable 处理恢复,而非应用层聚合。应用程序可以使用 SQL 或物化视图构建小时级或日级汇总表,而 Durable 将保留由检查点捕获的数据库状态。

V1 不会自动汇总原始数据,也不会对选定的表或分区执行检查点。checkpoint() 始终运行完整的 BACKUP DATABASE

本地 TTL 限制当前数据库的逻辑内容。V1 不会删除被新 head 取代的检查点和 WAL 段,因此它本身不会在对象存储中强制执行物理保留期限、删除策略或成本上限。

绑定状态 {#binding-status}

截至 2026 年 9 月 4 日的状态:

组件状态
chdb-corePR #202 已合并;v26.7.2-rc.2 提供了备份、恢复和查询分析的 C ABI。
Pythonchdb.durable 在 v4.3.0 中发布;该实现早于冻结的 V1 协议,仍需要进行完整的 V1 一致性工作。
Node.jsPR #90 实现了纯 TypeScript 控制平面;原生适配器和 npm 发布仍在进行中。
Go计划针对相同的核心 ABI 和 V1 一致性测试套件进行开发。
Rust会话(Session)和路径生命周期优先,随后是相同的 Durable V1 协议。

稍后发布的绑定仍然实现 V1;发布顺序不定义新的协议版本。

路线图 {#roadmap}

近期工作是发布 V1 的测试固件和场景,然后让 Python、Node.js 和 Go 通过相同的跨绑定一致性测试套件。Rust 将在其会话模型准备就绪后加入。

V2 的候选功能包括:可移植的增量检查点、Parquet 或数据 WAL、可感知可达性的垃圾回收、全局状态恢复,以及跨备份格式的迁移。选择性检查点和通用汇总原语需要一个单独的提案,以区分恢复机制与应用聚合策略。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐