产品指南
时间旅行

时间旅行

时间旅行允许查询数据库在特定时间点的状态。这个功能通过使用 FOR SYSTEM_TIME AS OF 语法来实现,被形象地称为"时间旅行"或"时光回溯"。

功能概述

FOR SYSTEM_TIME AS OF 语法可以让您指定一个时间点,查询表或物化视图在该时间点的数据状态。这个功能可以应用于多种场景,如解决事务冲突、恢复误删数据以及历史数据问题定位等。

使用场景

1. 解决事务冲突

在高并发场景下,经常会遇到事务冲突的问题。通过指定一个较早的时间点,当前查询就不会与后续的读写操作产生冲突。如果您可以接受数据有一定的延迟,这是一种很好的解决事务冲突的方法。

2. 恢复误删数据

如果不小心删除了表中的某些数据,可以通过指定删除操作之前的时间点来查询和恢复这些数据。

3. 历史数据问题定位

在诊断和排查历史数据问题时,可以通过指定不同的时间点来查看数据的变更过程,从而更好地定位和解决问题。

使用限制

需要注意的是,指定的时间点只能是当前时间往前推23小时以内。也就是说,您最多只能查询到23小时之前的数据状态。如果需要查询更久的时间,可以通过备份恢复功能。

使用方法

下面我们通过一些具体的示例来说明如何使用 FOR SYSTEM_TIME AS OF 语法。

1. 在单表上查询

SELECT COUNT(1) FROM t1 FOR SYSTEM_TIME AS OF '-10s' WHERE id = 5;

这个查询将返回在10秒钟之前的时间点,t1表中 id 为 5 的记录数。

2. 关联时为每个表指定时间

SELECT t1.col1, t2.col2
FROM t1 FOR SYSTEM_TIME AS OF '-30m', t2 FOR SYSTEM_TIME AS OF '-1h'
WHERE t1.id = t2.id;

在这个查询中,t1 表的数据是30分钟之前的状态,而 t2 表的数据是1小时之前的状态。您可以根据需要为每个表指定不同的时间点。

3. 事务上指定时间

BEGIN FOR SYSTEM_TIME AS OF '-60s';
-- 在这个事务中的所有查询都将读取60秒前的数据
SELECT * FROM t1;
COMMIT;

通过在事务开始时指定时间点,该事务中的所有查询都将读取指定时间点的数据状态。

4. 物化视图指定时间

CREATE MATERIALIZED VIEW mv AS SELECT id FROM t1;
SELECT * FROM mv FOR SYSTEM_TIME AS OF '-1s';

这个查询将返回物化视图 mv 在1秒钟之前的数据状态。

5. 通过指定时间戳来查询

# date -d '2024-09-30 15:15:00' +%s%N
1727680500000000000
 
SELECT * FROM t1 FOR SYSTEM_TIME AS OF '1727680500000000000';

在这个示例中,我们首先使用 date 命令获取 2024-09-30 15:15:00 这个时间点对应的纳秒级时间戳 1727680500000000000。然后在查询中使用 FOR SYSTEM_TIME AS OF '1727680500000000000' 语法,即可查询表 t1 在该时间点的数据状态。