DeepSeek总结的chDB Durable概述
标题: ‘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}
该设计包含三个层级:
- 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_format和min_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-core | PR #202 已合并;v26.7.2-rc.2 提供了备份、恢复和查询分析的 C ABI。 |
| Python | chdb.durable 在 v4.3.0 中发布;该实现早于冻结的 V1 协议,仍需要进行完整的 V1 一致性工作。 |
| Node.js | PR #90 实现了纯 TypeScript 控制平面;原生适配器和 npm 发布仍在进行中。 |
| Go | 计划针对相同的核心 ABI 和 V1 一致性测试套件进行开发。 |
| Rust | 会话(Session)和路径生命周期优先,随后是相同的 Durable V1 协议。 |
稍后发布的绑定仍然实现 V1;发布顺序不定义新的协议版本。
路线图 {#roadmap}
近期工作是发布 V1 的测试固件和场景,然后让 Python、Node.js 和 Go 通过相同的跨绑定一致性测试套件。Rust 将在其会话模型准备就绪后加入。
V2 的候选功能包括:可移植的增量检查点、Parquet 或数据 WAL、可感知可达性的垃圾回收、全局状态恢复,以及跨备份格式的迁移。选择性检查点和通用汇总原语需要一个单独的提案,以区分恢复机制与应用聚合策略。
更多推荐



所有评论(0)