Apache Doris 的时间旅行与快照能力:边界、替代路径与可落地操作

摘要 :历史版本回溯在 Apache Doris 官方文档中分三条路径落地,其商业化公司 SelectDB 提供云上托管形态,但 Time Travel 能力在官方文档中标注为即将发布。其一,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)。截至 2026 年 10 月核查,官方文档未检索到 Doris 内表(OLAP 表)对应的 Time Travel 语法;zero-copy clone 同样未在官方文档中检索到对应语法,替代路径为 CTAS、CREATE TABLE ... LIKE 与上述替换语句的组合。本文给出逐条可执行 SQL 与确认配置生效的验证方法。

一、先说结论

命中以下任意两条,建议按下表对应路径设计,而不是先去寻找一个全局开关:需要按时间点回溯某张表;需要在较短时间内给测试环境拉一份与生产同等规模的副本;需要数据版本可回滚且切换过程无空窗期;误删除、误 DROP 之后需要找回;集群部署在存算分离模式下需要长期归档。

诉求 官方可用路径 关键事实
按时间点读历史数据 Iceberg / Paimon / Lance / Hudi 外部表 + FOR TIME AS OF Iceberg Time Travel 自 2.1 版 Catalog 文档即已收录;$snapshots / $history 系统表写法自 3.1.0 起
误删对象找回 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 等外部湖表的文档页,内表未检索到对应的 Time Travel 语法。下文按这条边界展开替代操作。

二、问题怎么产生

第一层,Time Travel 的前提是"多次提交各自留下可定位的元数据"。 Iceberg、Paimon、Lance 这类开放湖格式每次 commit 会生成一个快照或版本号,旧版本的数据文件仍被快照元数据引用,查询引擎可用时间点或版本号直接定位某次提交的结果集。Doris 在这条链路上承担查询引擎角色,语法语义在官方文档中完整给出。

第二层,可回溯窗口并不由查询引擎统一控制。 对外部湖表,能回溯多久取决于湖格式自身的快照保留策略,例如 Iceberg 侧的 ALTER TABLE sales.orders EXECUTE expire_snapshots ("retain_last" = "5"); 会把可回溯范围收敛到最近 5 个快照;Doris 官方文档未记载全局的 Time Travel 保留期参数。

第三层,误删、误覆盖、长期归档是三种不同诉求。 误删针对元数据对象,官方用回收站机制承接;误覆盖针对数据内容,需要"影子区加原子切换"的写入范式;长期归档针对时间跨度远大于前两者的场景,落到 Repository 快照。若用同一个词覆盖这三类诉求,容易出现路径错配。

三、怎么做:实操路径

3.1 Iceberg 外部湖表的历史版本查询

sql 复制代码
-- 按时间戳读历史数据
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;

版本口径:FOR TIME AS OF / FOR VERSION AS OF 自 2.1 版 Iceberg Catalog 文档即已收录;系统表写法 <table>$<system_table_name> 自 3.1.0 起,Branch / Tag 语法 @branch(branch1)、@tag(tag1) 同样自 3.1.0 起。自 4.1.4 起 iceberg_meta() 表函数被移除,统一改用上述系统表写法。

实操验证 :执行 SELECT * FROM iceberg_table$history; 应返回历史提交记录,确认快照元数据已生成;若返回空集,说明该表尚未产生过多次提交,Time Travel 无可回溯窗口。

3.2 Paimon / Hudi / Lance 的语法与版本差异

sql 复制代码
-- Paimon:查看快照清单
SELECT snapshot_id, commit_time FROM paimon_tbl$snapshots;

-- 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";

-- Hudi:3.0 文档收录的写法
SELECT * FROM customer_cow FOR TIME AS OF '20240603015018572' WHERE c_custkey = 32;

-- Lance(4.x):版本号 / 时间 / tag / branch
SELECT * FROM lance_catalog.db.tbl FOR VERSION AS OF 2;
SELECT * FROM lance_catalog.db.tbl@tag(v2);
SELECT * FROM lance_catalog.db.tbl@branch(dev) FOR VERSION AS OF 2;

Hudi 侧的已知限制:3.0 文档记录 Time Travel 语法当时不被新优化器支持,需先执行 set enable_nereids_planner=false;,文档表述为该问题会在后续版本修复;当前版本是否仍有该限制,本次未核实。

3.3 快照过期的维护动作

sql 复制代码
ALTER TABLE sales.orders EXECUTE expire_snapshots ("retain_last" = "5");

Doris 可直接对湖表执行维护操作,历史回溯窗口因此成为可用 SQL 管理的变量。官方同时指出,Trino 或 Spark 指向同一个 REST / HMS Catalog 时,读到的是 Doris 刚产生的同一批快照。

3.4 误删对象的恢复

sql 复制代码
RECOVER DATABASE example_db;
RECOVER TABLE example_db.example_tbl;
RECOVER PARTITION p1 FROM example_tbl;
RECOVER TABLE example_db.example_tbl AS new_example_tbl;

-- 列出当前可恢复清单
SHOW CATALOG RECYCLE BIN;

这条路径恢复的是一段时间内删除的元信息,默认窗口 1 天,由 FE 配置文件中的 catalog_trash_expire_second 调整,执行账号需要 ADMIN_PRIV 权限。注意临时分区被删除后不能用 RECOVER 恢复。该参数只控制回收站,与时间旅行无关。

实操验证 :执行 SHOW CATALOG RECYCLE BIN; 应返回处于回收站保护期内的对象清单;若目标表不在清单中,说明已超过 catalog_trash_expire_second 设定的窗口,需走 Repository 备份恢复。

3.5 分区表的原子覆盖写

适用于"重跑某个分区后整体替换",全程正式分区对外可读:

sql 复制代码
-- 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 ...;
SELECT ... FROM tbl1 TEMPORARY PARTITION(tp1) JOIN tbl2 TEMPORARY PARTITION(tp1) ON ...;

-- 3. 原子替换
ALTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);

三条使用注意:替换成功后被替换的正式分区被删除且不可恢复;表上存在临时分区时无法执行 Schema Change / Rollup;use_temp_partition_name 在待替换分区数与替换分区数不等时失效,强制使用临时分区名。

3.6 非分区表的整表替换

sql 复制代码
-- swap 默认 true:两表互改表名,为重命名级元数据操作
ALTER TABLE tbl1 REPLACE WITH TABLE tbl2;

-- swap = false:保留 tbl1 这个名字承载 tbl2 的数据,原 tbl1 被删除且无法恢复
ALTER TABLE tbl1 REPLACE WITH TABLE tbl2 PROPERTIES('swap' = 'false');

官方给出的实践是先用 CREATE TABLE LIKE 建同构空表、灌入新数据,再执行替换,避免先删后导造成的空窗期。该语句不检查两表结构是否一致,替换也不会改写权限。

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

sql 复制代码
CREATE REPOSITORY `s3_repo`
WITH S3
ON LOCATION "s3://bucket_name/s3_repo"
PROPERTIES
(
    "s3.endpoint" = "https://s3.us-east-1.amazonaws.com",
    "s3.region" = "us-east-1",
    "s3.access_key" = "ak",
    "s3.secret_key" = "sk"
);

Repository 支持 S3、Azure(自 3.1.3 起)、GCP、OSS、MinIO、HDFS;MinIO 未启用 Virtual Host-style 时需补 "use_path_style" = "true"。备份与查看:

sql 复制代码
BACKUP SNAPSHOT exampledb_20241225 TO example_repo;
SHOW BACKUP;
SHOW SNAPSHOT ON example_repo;
CANCEL BACKUP FROM db_name;

恢复时需要从 SHOW SNAPSHOT 的 Timestamp 列取 backup_timestamp,支持跨库恢复、单表恢复、分区恢复与 AS 重命名:

sql 复制代码
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");

官方对恢复流程的描述是"从 Repository 下载快照并还原到目标 Doris 集群",SHOW RESTORE 输出中包含 DownloadFinishedTime 阶段字段。可以确定的是:Doris 备份仅支持全量,官方文档给出的近似方案是备份特定分区来近似增量效果。

实操验证 :SHOW BACKUP 的 State 列变为 FINISHED 后,再用 SHOW SNAPSHOT ON example_repo 确认快照已登记;恢复时用 SHOW RESTORE 跟踪 DownloadFinishedTime 字段确认下载完成,再核对目标表数据。

3.8 库表副本的替代路径

官方文档未检索到 CLONE 类语法,可组合使用下面两类语句:

sql 复制代码
-- 复制结构:只复制列定义与列属性,不复制数据;只能对内表使用
CREATE TABLE orders_staging LIKE sales.orders;

-- 复制结构与数据:列名与类型可从查询结果推断
CREATE TABLE orders_snapshot AS SELECT * FROM sales.orders;

CREATE TABLE ... LIKE 的限制是官方明确的:只能对 Doris 内表使用;只有显式指定的 rollup 才会被复制;所有同步物化视图都不会被复制。需要"影子表加原子切换"时,用 LIKE 建空表 → 灌数 → ALTER TABLE tbl1 REPLACE WITH TABLE tbl2(swap=true)三步完成。

3.9 相关参数速查

参数 / 语法项 建议值 / 示例 作用 适用场景
catalog_trash_expire_second 默认 1 天 控制删除对象的回收站保留期,决定 RECOVER 时间窗口 误删恢复
strict_range 默认 true,List 分区恒为 true 是否要求替换前后分区范围严格对齐 REPLACE PARTITION
use_temp_partition_name 默认 false 替换后是否沿用临时分区名,分区数不等时失效 REPLACE PARTITION
swap 默认 true true 为两表互改表名,false 为删除原表后改名且不可恢复 REPLACE WITH TABLE
backup_timestamp 取自 SHOW SNAPSHOT 的 Timestamp 列 指定还原到哪一个 Repository 快照 RESTORE
retain_last 示例值为 5 控制湖表保留最近多少个快照,等价于收敛可回溯窗口 expire_snapshots
use_path_style MinIO 未启用 Virtual Host-style 时置 true 修正对象存储寻址方式,避免创建 Repository 失败 S3 / MinIO Repository

3.10 云上托管侧的口径

云上托管官方安全特性页在"容灾保护"条目下原文列出"支持 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) / BEFORE(STATEMENT => 'query_id'),必须紧跟对象名之后
保留窗口控制 由湖格式快照过期策略决定,如 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 天,官方表述为只有 Snowflake 能恢复
存储记账 Time Travel 存储即湖表快照存储,随快照过期策略变化 Active / Time Travel / Fail-safe 三态均计入存储账单,TABLE_STORAGE_METRICS 提供指标列
表克隆 未检索到 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 承担连续数据保护;跨区域通过 replication group / failover 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

六、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 恢复,必要时用 AS 重命名避免与原表名冲突。注意临时分区被删除后不能用 RECOVER 恢复。

Q:存算分离集群怎么做备份?

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

Q:云上托管版本的 TimeTravel 现在能用吗?

按官方文档,云上托管安全特性页在"容灾保护"条目下的原文是"支持 Warehouse 级别 TimeTravel(即将发布)",属于尚未发布的能力。同一页面同时记载对象存储默认开启 versioning,在应用层面保证对象多版本冗余,这部分是已上线的表述。

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

相关推荐
2601_961963381 小时前
电子合同检索与全文搜索怎么测、怎么选:六个指标 + 五家平台对比 + 八个自测问题
数据库·后端·python·django·智能合约
zhangjw342 小时前
1-3 PostgreSQL 架构模型:实例、数据库、Schema 模式、表空间完整概念
数据库·postgresql·架构
小羊没烦恼!2 小时前
C#综合揭秘——Entity Framework 并发处理详解
java·开发语言·前端·javascript·数据库·mysql·c#
Databend2 小时前
周年庆结束了,湖仓为什么还在高消费?
大数据·数据库·agent
笃行3502 小时前
数据集成软件里最贵的一行字,叫“用同步工具做增量同步“
数据库
吴声子夜歌2 小时前
Docker入门与实战——Etcd(高可用的键值数据库)
数据库·docker·etcd
qq_白羊座3 小时前
Hologres / PostgreSQL jsonb 常用函数 & 操作符对照表
数据库·postgresql
千桐科技3 小时前
qData 数据中台专业版功能解析:告别 Excel 与 SQL 拼凑,打通系统合并的可追踪数据链路
数据库·sql·excel·qdata
jiushidt3 小时前
在 DBeaver 中为 SQLite 启用 SpatiaLite
数据库·sqlite