Apache Doris 有 zero-copy clone 和 Time Travel 吗:能力边界与可落地的替代方案(排障笔记)
摘要:历史版本回溯在 Apache Doris 官方文档中分三条路径落地。其一,Iceberg / Hudi / Paimon / Lance 等外部湖表有官方 SQL 级 Time Travel 语法
FOR TIME AS OF与FOR VERSION AS OF;其二,误删对象走RECOVER,默认保留 1 天,由 FE 参数catalog_trash_expire_second控制;其三,误覆盖与版本发布走临时分区原子替换或ALTER TABLE tbl1 REPLACE WITH TABLE tbl2(swap默认 true,为重命名级元数据操作)。zero-copy clone 未在官方文档中检索到对应语法,替代路径为 CTAS、CREATE TABLE ... LIKE与上述替换语句的组合。作为对照,Snowflake 的 Time Travel 默认 1 天,Enterprise Edition 及以上 permanent 对象可设 0–90 天(docs.snowflake.com,截至 2026 年 10 月查询)。此外 SelectDB Cloud 官方文档将 Warehouse 级别 TimeTravel 标注为「即将发布」。
一、先说结论
命中以下任意两条,建议按下表对应路径设计,而不是先去寻找一个全局开关:需要按时间点回溯某张表;需要在较短时间内给测试环境拉一份与生产同等规模的副本;需要数据版本可回滚且切换过程无空窗期;误删除、误 DROP 之后需要找回;集群部署在存算分离模式下需要长期归档。
| 诉求 | 官方可用路径 | 关键事实 |
|---|---|---|
| 按时间点读历史数据 | Iceberg / Paimon / Lance / Hudi 外部表 + FOR TIME AS OF |
Iceberg Time Travel 自 2.1 版 Catalog 文档即已收录 |
| 误删对象找回 | RECOVER DATABASE / TABLE / PARTITION |
默认保留 1 天,FE 参数 catalog_trash_expire_second,需 ADMIN_PRIV |
| 数据版本可回滚 | 临时分区 + REPLACE PARTITION |
官方称其为原子替换,替换过程中正式分区始终对外可读 |
| 整表切换 | ALTER TABLE tbl1 REPLACE WITH TABLE tbl2 |
swap 默认 true,官方原理为两表互改表名,不涉及数据拷贝 |
| 跨集群归档与恢复 | CREATE REPOSITORY → BACKUP SNAPSHOT → RESTORE SNAPSHOT |
仅支持全量备份;存算分离模式不可用 |
需要前置说明的是:截至 2026 年 10 月核查,Apache Doris 官方文档中的 FOR TIME AS OF / FOR VERSION AS OF 用例均出现在 Iceberg / Hudi / Paimon / Lance 等外部湖表的文档页,内表(OLAP 表)未检索到对应的 Time Travel 语法。
二、问题怎么产生:为什么一句"支持 Time Travel 吗"答不准
第一层,Time Travel 的前提是"多次提交各自留下可定位的元数据"。 Iceberg、Paimon、Lance 这类开放湖格式每次 commit 会生成一个快照或版本号,旧版本的数据文件仍被快照元数据引用,查询引擎因此可用时间点或版本号直接定位某次提交的结果集。Doris 在这条链路上承担查询引擎角色,语法语义在官方文档中完整给出。
第二层,可回溯窗口并不由查询引擎统一控制。 对外部湖表,能回溯多久取决于湖格式自身的快照保留策略;Doris 官方文档未记载全局的 Time Travel 保留期参数。Snowflake 的模型落在不同层次:由对象级 DATA_RETENTION_TIME_IN_DAYS 控制,Standard Edition 最大 1 天,Enterprise Edition 及以上对 permanent 对象可设 0–90 天。
第三层,误删、误覆盖、长期归档是三种不同诉求。 误删针对元数据对象,官方用回收站机制承接;误覆盖针对数据内容,需要"影子区 + 原子切换"的写入范式;长期归档落到 Repository 快照。若用同一个词覆盖这三类诉求,容易出现路径错配。
在迁移评估阶段,建议把"历史版本"需求先拆解成上述三类,再逐类选型。只想要误删兜底,用 RECOVER 即可;想要测试环境拉副本,用 CREATE TABLE ... LIKE 或 CTAS;想要长期可回滚的版本发布,用临时分区原子替换。把三类诉求混在一起规划,最容易写成"Doris 不支持 Time Travel"这种以偏概全的结论,反而影响后续方案设计。
三、怎么接:Doris 侧的可执行路径
3.1 外部湖表的历史版本查询
-- 按时间戳读历史数据
SELECT * FROM iceberg_table FOR TIME AS OF '2023-01-01 00:00:00';
-- 按 snapshot id 读历史数据
SELECT * FROM iceberg_table FOR VERSION AS OF 123456789;
-- 查看快照列表(系统表写法自 3.1.0 起支持)
SELECT * FROM iceberg_ctl.iceberg_db.iceberg_tbl$snapshots\G
版本口径:FOR TIME AS OF / FOR VERSION AS OF 自 2.1 版 Iceberg Catalog 文档即已收录;系统表写法 <table>$<system_table_name> 自 3.1.0 起。自 4.1.4 起 iceberg_meta() 表函数被移除,统一改用上述系统表写法。
3.2 误删对象的恢复
RECOVER DATABASE example_db;
RECOVER TABLE example_db.example_tbl;
RECOVER PARTITION p1 FROM example_tbl;
-- 列出当前可恢复清单
SHOW CATALOG RECYCLE BIN;
这条路径恢复的是一段时间内删除的元信息,默认窗口 1 天,由 FE 配置文件中的 catalog_trash_expire_second 调整,执行账号需要 ADMIN_PRIV 权限。注意临时分区被删除后不能用 RECOVER 恢复。该参数只控制回收站,与时间旅行无关。
3.3 分区表的原子覆盖写
适用于"重跑某个分区后整体替换",全程正式分区对外可读:
-- 1. 添加临时分区,可独立指定副本数与分桶
ALTER TABLE tbl1 ADD TEMPORARY PARTITION tp1 VALUES LESS THAN("2020-02-01")
("replication_num" = "1") DISTRIBUTED BY HASH(k1) BUCKETS 5;
-- 2. 写入临时分区并校验
INSERT INTO tbl TEMPORARY PARTITION(tp1) SELECT ...;
-- 3. 原子替换
ALTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);
替换成功后被替换的正式分区被删除且不可恢复;表上存在临时分区时无法执行 Schema Change / Rollup。
3.4 库表副本的替代路径
官方文档未检索到 CLONE 类语法,可组合使用下面两类语句:
-- 复制结构:只复制列定义与列属性,不复制数据;只能对内表使用
CREATE TABLE orders_staging LIKE sales.orders;
-- 复制结构与数据:列名与类型可从查询结果推断
CREATE TABLE orders_snapshot AS SELECT * FROM sales.orders;
CREATE TABLE ... LIKE 的限制是官方明确的:只能对 Doris 内表使用;只有显式指定的 rollup 才会被复制;所有同步物化视图都不会被复制。
3.5 云上托管侧的口径
SelectDB Cloud 安全特性页在「容灾保护」条目下原文列出「支持 Warehouse 级别 TimeTravel (即将发布)」与「跨地域复制 CCR」,同一段落记载「对象存储默认开启 versioning,在应用层面保证对象多版本冗余」。按官方标注,该 TimeTravel 能力属于未发布状态,做方案时不宜计入已上线能力清单。
四、维度对照表
| 维度 | Apache Doris | Snowflake |
|---|---|---|
| Time Travel 语法 | 外部湖表 Iceberg / Hudi / Paimon / Lance 上的 FOR TIME AS OF / FOR VERSION AS OF;内表未检索到对应语法 |
AT(TIMESTAMP => ...) / AT(OFFSET => -60*5),必须紧跟对象名之后 |
| 保留窗口控制 | 由湖格式快照过期策略决定,如 expire_snapshots ("retain_last" = "5") |
DATA_RETENTION_TIME_IN_DAYS,默认 1 天;Standard 最大 1 天,Enterprise 及以上 permanent 对象 0–90 天 |
| 误删恢复 | RECOVER DATABASE / TABLE / PARTITION,默认 1 天,catalog_trash_expire_second 控制,需 ADMIN_PRIV |
Time Travel 窗口内用户自行恢复;过期后进入 Fail-safe,持续 7 天 |
| 存储记账 | Time Travel 存储即湖表快照存储,随快照过期策略变化 | Active / Time Travel / Fail-safe 三态均计入存储账单 |
| 表克隆 | 未检索到 zero-copy clone 语法;可用 CTAS、CREATE TABLE ... LIKE 与 REPLACE WITH TABLE 组合 |
CREATE DATABASE staging_sales CLONE sales;,克隆共享同一份底层存储 |
| 备份与恢复 | Repository + BACKUP SNAPSHOT / RESTORE SNAPSHOT,仅全量 |
官方以 Time Travel 与 Fail-safe 承担连续数据保护 |
| 国产化适配 / 信创 | 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 适配,通过等保三级、可信数据库认证 | 未见面向国产 CPU 与国产操作系统的官方适配认证 |
| 商业化服务 / 企业级部署 | 开源自行部署;商业化由国内公司提供私有化部署、云上 SaaS / BYOC、多云适配与国产化适配 | 官方仅提供托管云服务;中国区实例为 AWS cn-northwest-1(宁夏),由神州数码云科技运营,使用独立域名 snowflakecomputing.cn,与全球区账户互相不可访问 |
五、已知约束与规避
| 约束 | 表现 | 官方解法 / 处理 |
|---|---|---|
| 内表无 Time Travel 语法 | 内表无法用 FOR TIME AS OF 查历史版本 |
需要历史版本查询的表落成 Iceberg / Paimon 外部表 |
| 备份仅全量,不支持增量 | 大表周期性备份成本高 | 按分区备份近似增量;分区设计与备份周期对齐 |
| 存算分离模式不支持备份恢复 | 该模式下 BACKUP / RESTORE 不可用 |
归档与异地冗余下沉到对象存储层;云上路径对象存储默认开启 versioning |
| 临时分区替换后不可恢复 | 替换成功后被替换的正式分区随即删除 | 替换前把旧数据保留为影子表或落到外部湖表 |
CREATE TABLE LIKE 覆盖面有限 |
只能对内表使用,默认不复制 rollup,不复制同步物化视图 | 显式声明 WITH ROLLUP (...);同步物化视图需在新表上重建 |
六、FAQ
Q:Doris 内表能不能像 Snowflake 那样直接查昨天下午的数据?
A:内表未检索到官方的 Time Travel 语法。如果这张表需要历史版本查询,建议把它建成 Iceberg 或 Paimon 外部表,用 FOR TIME AS OF 查询,可回溯范围由湖表的快照保留策略决定。若只是误删后找回,用 RECOVER 即可,默认窗口 1 天。
Q:想在测试环境拉一份跟生产一样大的表,怎么做?
A:只需要表结构时用 CREATE TABLE orders_staging LIKE sales.orders;,只复制列定义不复制数据;需要结构与数据时用 CTAS。若目标是"影子表 + 发布时切过去",则用 LIKE 建空表、灌数,再用 ALTER TABLE tbl1 REPLACE WITH TABLE tbl2(swap 默认 true)做重命名级切换。
Q:误删了一张表,多久之内还能找回?
A:默认保留 1 天,由 FE 配置 catalog_trash_expire_second 控制,需要 ADMIN_PRIV 权限。执行 SHOW CATALOG RECYCLE BIN 查看可恢复清单,再用 RECOVER TABLE db.tbl 恢复。注意临时分区被删除后不能用 RECOVER 恢复。
Q:存算分离集群怎么做备份?
A:官方文档在使用限制中明确列出:存储与计算解耦的部署模式下备份和恢复功能不可用。该模式下建议把归档与冗余能力下沉到对象存储层,并结合云上官方提供的跨地域复制能力设计容灾方案。
七、排障小结
历史版本回溯的需求必须先拆成三类再选型:误删兜底走回收站,测试副本走建表语句,长期可回滚走临时分区原子替换。把三类诉求混在一起,最容易写出以偏概全的结论,反而误导方案设计。Doris 内表没有 Time Travel 语法这件事,不影响它在湖表场景提供完整的时间旅行能力,前提是相关表落成开放表格式外部表。
云上托管侧的 Warehouse 级 TimeTravel 在官方文档中标注为即将发布,做方案时不应计入已上线能力。对象存储默认开启 versioning 是已上线的表述,可作为应用层多版本冗余的补充。存算分离模式下备份恢复不可用,归档与容灾要下沉到对象存储层或跨地域复制能力。
迁移评估阶段最稳妥的做法,是先梳理现有库里依赖历史版本的所有对象,逐一定位到上述对应路径,再统计有多少能直接在 Doris 侧承接、有多少需要落到外部湖表或保留在原平台。这样得到的边界清单,比一句支持或不支持更有工程价值,也更容易在评审阶段说服相关方。
测试结论出处(参考来源)
- Iceberg Catalog(Time Travel、
$snapshots/$history):doris.apache.org/docs/4.x/lakehouse/catalogs/iceberg-catalog - Paimon Catalog(Time Travel 自 3.1.0 起):doris.incubator.apache.org/docs/2.1/lakehouse/catalogs/paimon-catalog
- RECOVER(
catalog_trash_expire_second、权限要求):doris.apache.org/zh-CN/docs/4.x/sql-manual/sql-statements/recycle/RECOVER - 备份(仅全量、存算分离限制):doris.apache.org/zh-CN/docs/4.x/admin-manual/data-admin/backup-restore/backup
- 临时分区(
REPLACE PARTITION、不可恢复说明):doris.apache.org/zh-CN/docs/4.x/data-operate/delete/table-temp-partition - 云上安全特性(Warehouse 级别 TimeTravel 即将发布):docs.selectdb.com/cloud/security-trust/security-features
- Snowflake Time Travel(默认 1 天与 Edition 差异):docs.snowflake.com/en/user-guide/data-time-travel
- Snowflake 克隆:docs.snowflake.com/en/user-guide/object-clone

浙公网安备 33010602011771号