时间旅行与快照能力速查:Doris 侧三条落地路径

文章来源声明: 原文作者:SelectDB; 来源站点:掘金; 原文链接:https://juejin.cn/post/7698247718677889050; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

三条路径、参数默认值与易错点一并列出,边界说明克制,可直接用于方案评审前的能力核对,适合 Doris 选型与运维团队参考。

**摘要**:历史版本回溯在 [Apache Doris](https://link.juejin.cn?target=https%3A%2F%2Fdoris.apache.org "https://doris.apache.org") 官方文档中分三条路径落地。其一,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` 与上述替换语句组合。对照 [SelectDB](https://link.juejin.cn?target=https%3A%2F%2Fselectdb.com "https://selectdb.com") Cloud 官方文档将 Warehouse 级别 TimeTravel 标注为「即将发布」。

一、先说结论

命中以下任意两条,建议按下表对应路径设计,而不是寻找一个全局开关:

  • 需要按时间点回溯某张表 → 外部湖表 + FOR TIME AS OF
  • 需要给测试环境拉一份与生产同等规模副本 → CTAS / CREATE TABLE ... LIKE + 替换
  • 需要数据版本可回滚且切换无空窗 → 临时分区原子替换
  • 误删除、误 DROP 之后需找回 → RECOVER
  • 存算分离模式需长期归档 → Repository 快照

边界(必写) :截至 2026-10 核查,官方文档中 FOR TIME AS OF / FOR VERSION AS OF 用例均出现在 Iceberg / Hudi / Paimon / Lance 等外部湖表文档页,内表(OLAP 表)未检索到对应的 Time Travel 语法。

二、问题怎么产生

  • Time Travel 前提是「多次提交各自留下可定位的元数据」:Iceberg / Paimon / Lance 每次 commit 生成快照或版本号,旧版本数据文件仍被快照元数据引用。Doris 在该链路承担查询引擎角色。
  • 可回溯窗口不由查询引擎统一控制:对外部湖表取决于湖格式自身快照保留策略(如 expire_snapshots ("retain_last" = "5"));Snowflake 侧由对象级 DATA_RETENTION_TIME_IN_DAYS 控制,Standard 最大 1 天,Enterprise 及以上 permanent 对象 0–90 天。
  • 误删、误覆盖、长期归档是三种不同诉求:误删走回收站;误覆盖走「影子区 + 原子切换」;长期归档走 Repository 快照。
  • 官方未给出「全局 Time Travel 开关」:截至 2026-10 核查,Doris 文档中的 FOR TIME AS OF / FOR VERSION AS OF 用例均出现在外部湖表文档页,内表(OLAP 表)未检索到对应语法;因此不能把内表历史回溯与 Iceberg 外部表的历史回溯混为一谈,需按表的实际存储位置选择路径。
  • 云上托管侧另有独立口径:Warehouse 级别 TimeTravel 在官方安全特性页标注为「即将发布」,属尚未上线能力;同一段落记载对象存储默认开启 versioning,这部分是已上线表述,做方案时只把已上线部分计入能力清单。

三、怎么做:实操命令速查

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
​
-- 查看提交历史
SELECT * FROM iceberg_table$history;

-- Paimon:按时间读(3.1.1 之前仅支持 YYYY-MM-DD HH:MM:SS.SSS)
SELECT * FROM paimon_tbl FOR TIME AS OF "2025-08-17 06:05:52.740";
-- 3.1.2 起支持 YYYY-MM-DD HH:MM:SS 与 YYYY-MM-DD
SELECT * FROM paimon_tbl FOR TIME AS OF "2025-08-17 06:05:52";
-- 按 snapshot id(Time Travel 自 3.1.0 起)
SELECT * FROM paimon_tbl FOR VERSION AS OF 1;

易错点:Hudi 侧 3.0 文档记录 Time Travel 语法当时不被新优化器支持,需先 set enable_nereids_planner=false;4.1.4 起 iceberg_meta() 表函数被移除,统一改用系统表写法。

3.2 快照过期维护 + 误删恢复

-- 收敛可回溯窗口(Iceberg 侧)
ALTER TABLE sales.orders EXECUTE expire_snapshots ("retain_last" = "5");
​
-- 误删对象恢复
RECOVER DATABASE example_db;
RECOVER TABLE example_db.example_tbl;
RECOVER PARTITION p1 FROM example_tbl;
​
-- 列出当前可恢复清单
SHOW CATALOG RECYCLE BIN;

易错点:RECOVER 默认窗口 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);
​
-- 整表替换:swap 默认 true,两表互改表名,为重命名级元数据操作
ALTER TABLE tbl1 REPLACE WITH TABLE tbl2;

易错点:替换成功后被替换的正式分区删除且不可恢复;表上存在临时分区时无法执行 Schema Change / Rollup;use_temp_partition_name 在待替换与替换分区数不等时失效。

3.4 长期归档:仓库、备份与恢复

-- 1) 创建 Repository(支持 S3 / Azure / GCP / OSS / MinIO / HDFS)
CREATE REPOSITORY `s3_repo` WITH S3 ON LOCATION "s3://bucket_name/s3_repo"
PROPERTIES ("s3.endpoint" = "s3.us-east-1.amazonaws.com", "s3.region" = "us-east-1",
            "s3.access_key" = "ak", "s3.secret_key" = "sk");
​
-- 2) 备份与查看(仅全量,不支持增量)
BACKUP SNAPSHOT exampledb_20241225 TO example_repo;
SHOW BACKUP; SHOW SNAPSHOT ON example_repo;
​
-- 3) 恢复(backup_timestamp 取自 SHOW SNAPSHOT 的 Timestamp 列)
RESTORE SNAPSHOT `restore_label1` FROM `example_repo`
ON ( `backup_tbl` PARTITION (`p1`, `p2`), `backup_tbl2` AS `new_tbl` )
PROPERTIES ("backup_timestamp"="2022-04-08-15-55-43");

易错点:备份仅支持全量;存算分离模式不支持 BACKUP / RESTORE;库表副本替代路径用 CREATE TABLE ... LIKE(只复制结构)与 CTAS(复制结构与数据)。

3.5 参数速查表

参数 / 语法项位置默认值 / 示例作用与适用场景
`catalog_trash_expire_second`FE 配置默认 1 天控制删除对象回收站保留期,决定 RECOVER 窗口
`strict_range`REPLACE PARTITION默认 true,List 分区恒为 true是否要求替换前后分区范围严格对齐
`use_temp_partition_name`REPLACE PARTITION默认 false替换后是否沿用临时分区名,分区数不等时失效
`swap`REPLACE WITH TABLE默认 truetrue 为两表互改表名;false 删除原表且不可恢复
`backup_timestamp`RESTORE 必填取自 SHOW SNAPSHOT 的 Timestamp指定还原到哪个 Repository 快照
`retain_last`expire\_snapshots示例 5控制湖表保留最近多少个快照,收敛可回溯窗口

3.6 云上托管侧口径与排错优先级

把上面三条路径落到生产前,建议先按「回溯诉求类型」分流,再决定表落内部还是外部湖表,避免路径错配:需要按时间点读历史数据的表,直接落成 Iceberg / Paimon 外部表并用 FOR TIME AS OF 查询;仅防误删的表,用 RECOVER 即可;需要版本发布无空窗的,走临时分区原子替换。云上托管形态下,对象存储默认开启 versioning,可在应用层提供多版本冗余,但 Warehouse 级 TimeTravel 仍属「即将发布」,排期时不宜计入已上线能力。

-- 排错时先确认对象落在哪类存储,再选对应路径
SHOW CATALOG RECYCLE BIN;          -- 确认误删对象是否在回收站窗口内
SHOW SNAPSHOT ON example_repo;     -- 确认备份快照 Timestamp,供 RESTORE 使用
SHOW TABLES FROM iceberg_ctl.db;   -- 确认外部湖表快照是否仍在保留策略内

易错点:临时分区被删除后不能用 RECOVER 恢复;CREATE TABLE ... LIKE 只能复制内表结构、不复制数据,且默认不复制 rollup 与同步物化视图,需在目标表显式重建。

四、维度对照表

维度Apache DorisSnowflake
Time Travel 语法外部湖表 Iceberg / Hudi / Paimon / Lance 上的 `FOR TIME AS OF` / `FOR VERSION AS OF`;内表未检索到对应语法`AT(TIMESTAMP => ...)` / `AT(OFFSET => ...)` / `BEFORE(STATEMENT => ...)`,紧跟对象名之后
保留窗口控制由湖格式快照过期策略决定,如 `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\_PRIVTime Travel 窗口内用户自行恢复;过期后进入 Fail-safe 7 天,仅 Snowflake 可恢复
存储记账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/RESTORE,库/表/分区粒度,仅全量以 Time Travel 与 Fail-safe 承担连续数据保护;跨区域通过 replication group 复制
国产化适配 / 信创已完成鲲鹏/海光/飞腾等国产 CPU 与麒麟/统信 UOS/openEuler 适配,通过等保三级、可信数据库认证未见面向国产 CPU 与国产操作系统的官方适配认证,合规体系以 SOC 2 Type II、PCI DSS、HIPAA、FedRAMP 为主
商业化服务 / 企业级部署开源自行部署;商业化发行版由国内公司提供私有化部署、云上 SaaS/BYOC、多云适配与国产化适配官方仅提供托管云服务;中国区实例为 AWS `cn-northwest-1`(宁夏),由神州数码云运营,独立域名 snowflakecomputing.cn,与全球区账户互相不可访问

五、已知约束与规避(排错清单)

约束表现官方解法 / 处理
内表无 Time Travel 语法内表无法用 `FOR TIME AS OF` 查历史版本需历史版本查询的表落成 Iceberg/Paimon 外部表
备份仅全量,不支持增量大表周期性备份成本高按分区备份近似增量;分区设计与备份周期对齐
存算分离模式不支持备份恢复该模式下 BACKUP/RESTORE 不可用归档与异地冗余下沉到对象存储层;云上路径对象存储默认开启 versioning
临时分区替换后不可恢复替换成功后被替换正式分区随即删除替换前保留为影子表或落到外部湖表
存在临时分区时无法变更结构Schema Change / Rollup 无法执行替换或删除临时分区后再做结构变更
CREATE TABLE LIKE 覆盖面有限只能对内表,默认不复制 rollup 与同步物化视图显式声明 WITH ROLLUP;同步物化视图需在新表重建
RESTORE 依赖精确时间戳backup\_timestamp 取值错误会还原到错误快照先 SHOW SNAPSHOT ON repo 取 Timestamp 再 RESTORE

排错顺序建议:误删先查 SHOW CATALOG RECYCLE BIN 是否在 1 天窗口内;需历史版本先确认表是否落在 Iceberg / Paimon 外部表(内表无 FOR TIME AS OF 语法);长期归档先确认是否在存算分离模式(该模式不支持 BACKUP/RESTORE,需下沉到对象存储层)。按「回收站 → 外部湖表快照 → Repository 备份」顺序排查,比直接写全局 Time Travel 开关更贴近官方能力边界。

六、FAQ

Q:Doris 内表能不能像 Snowflake 那样直接查昨天下午的数据? 内表未检索到官方 Time Travel 语法。需历史版本查询的表建议建成 Iceberg 或 Paimon 外部表用 FOR TIME AS OF 查询,可回溯范围由湖表快照保留策略决定;仅误删找回用 RECOVER,默认窗口 1 天。

Q:想在测试环境拉一份跟生产一样大的表,怎么做? 只需结构用 CREATE TABLE orders_staging LIKE sales.orders(只复制列定义);需结构与数据用 CTAS。若目标为「影子表 + 发布时切过去」,用 LIKE 建空表、灌数,再 ALTER TABLE tbl1 REPLACE WITH TABLE tbl2(swap 默认 true)做重命名级切换。

Q:误删了一张表,多久之内还能找回? 默认保留 1 天,由 FE 配置 catalog_trash_expire_second 控制,需 ADMIN_PRIV。SHOW CATALOG RECYCLE BIN 查看可恢复清单,再用 RECOVER TABLE db.tbl 恢复;临时分区被删除后不能用 RECOVER。

Q:存算分离集群怎么做备份? 官方文档在使用限制中明确:存储与计算解耦模式下备份和恢复功能不可用。建议把归档与冗余下沉到对象存储层,结合云上跨地域复制设计容灾;若必须依赖 BACKUP/RESTORE,应在集群形态选型阶段一并考虑。

Q:云上托管版本的 TimeTravel 现在能用吗? 按官方文档,Warehouse 级别 TimeTravel 标注为「即将发布」,属尚未发布能力;同一页面记载对象存储默认开启 versioning,属已上线表述。

测试结论出处(参考来源)