闪回读取和备机读取

最近更新时间:2025-12-24 12:03:42

我的收藏

概述

闪回读取和备机读取是数据库系统中一种读取历史数据版本的机制。用户可以指定特定历史时间点或距离当前时间的时间间隔来获取数据库在过去某个时刻的数据快照。
闪回查询:当发生误操作(如 UPDATEDELETE 了错误的数据)时,可以通过查询误操作发生前的时间点,快速找回历史数据,极大地简化了数据恢复流程。TDSQL Boundless 提供了语句级别的闪回查询功能。
备机读取(Stale Read):在对数据实时性要求不高的读密集型业务场景中,可以将读请求转发到备机(Follower)节点。这在牺牲了秒级数据实时性的前提下,有效分担了主机(Leader)的读取压力,降低了读取延迟,提升了系统整体的资源利用率和吞吐能力。TDSQL Boundless 提供了语句级别、事务级别、会话级别三种级别的 Stale Read 功能,并且允许用户依据业务情况选择读取数据的副本角色。

支持版本

闪回查询支持17.0.0及以上版本。
备机读取支持20.0.0及以上版本。

使用限制

闪回查询功能用于在数据库运维过程中快速查询误操作前的历史数据。使用该功能时需注意以下几点:
1. 存储引擎限制
仅支持 RocksDB 引擎物理表
不支持视图、其他引擎表
不支持 last_insert_id() 等无实际列对应的函数
2. 时间点指定方式
混合逻辑时钟时间戳(GTS):精确定位到具体快照数据,如 SQL 指定29610460101738510的 GTS。
秒级闪回查询:查询指定秒内的最新写入数据,相当于逻辑部分全为1的混合逻辑时间戳。如 SQL 指定2025-01-01 12:00:00时间点。
不支持指定未来时间(返回错误 Can't stale read from the future)。
3. 操作限制
单条 SQL 仅支持一个闪回快照,即所有子查询共享同一闪回时间点,不可分别指定。
仅支持自动提交的无锁只读查询。不支持 SELECT FOR UPDATEFOR SHARELOCK IN SHARE MODE等锁定查询;不支持 INSERT...SELECT 语句;不支持 BEGIN; SELECT... 语法。
不支持 DDL 操作。若表结构发生变更,需通过回收站恢复表结构和数据。闪回查询的行为和数据取决于 DDL 的具体形式,结果不固定。
4. 数据范围限制
无法查询早于全局最早快照(GES)的数据。
GES 受 MC 参数 advance-global-earliest-snapshot-delay 控制。启用闪回功能会延迟 GES 推进,可能增加存储占用和查询耗时。

使用说明

准备工作

-- 启用闪回查询功能
SET persist tdsql_enable_stale_read = ON;

闪回查询使用说明

语法

闪回查询引入了全新的AS OF语法,查询指定时间点的数据。
SELECT ... FROM <table_name> [ AS OF {TIMESTAMP timestamp_option | GTS gts_option} ]
timestamp_option 支持类型
凡是可以get_date的表达式,都可以作为timestamp_option,包括但不限于:
时间字面值:'2023-09-05 12:00:00'
时间函数:NOW(), SYSDATE(), UTC_TIMESTAMP()
用户变量:SELECT NOW() INTO @time1
时间算术表达式:NOW + INTERVAL 1 SECOND,@time1 - INTERVAL 1 YEAR
gts_option 支持类型
凡是可以作为整数的表达式,都可以作为gts_option,包括但不限于:
整数字面值:29610460101738510
函数和算术表达式:((UNIX_TIMESTAMP(@time1) << 24) | 0xFFFFFF)
用户变量:@gts1

示例

-- 创建测试表
CREATE TABLE t1(a INT PRIMARY KEY, b INT);

SELECT sleep(3);

-- 记录初始时间点
SELECT NOW() INTO @time0;
SELECT ((UNIX_TIMESTAMP(@time0) << 24) | 0xFFFFFF) INTO @gts0;

SELECT sleep(3);

-- 插入测试数据
INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(4,4),(5,5),(6,1),(7,2),(8,3),(9,4),(10,5);

SELECT sleep(3);

-- 记录数据插入后时间点
SELECT NOW() INTO @time1;
SELECT ((UNIX_TIMESTAMP(@time1) << 24) | 0xFFFFFF) INTO @gts1;

SELECT sleep(3);

-- 更新数据
UPDATE t1 SET b=b*10;

-- 当前数据查询
SELECT * FROM t1 ORDER BY a;
a»b
1»10
2»20
3»30
4»40
5»50
6»10
7»20
8»30
9»40
10»■50

-- 闪回查询到初始状态(空表)
SELECT * FROM t1 ORDER BY a AS OF TIMESTAMP @time0;
a»b
SELECT * FROM t1 ORDER BY a AS OF GTS @gts0;
a»b

-- 闪回查询到插入数据后的状态
SELECT * FROM t1 ORDER BY a AS OF TIMESTAMP @time1;
a»b
1»1
2»2
3»3
4»4
5»5
6»1
7»2
8»3
9»4
10»■5


SELECT * FROM t1 ORDER BY a AS OF GTS @gts1;
a»b
1»1
2»2
3»3
4»4
5»5
6»1
7»2
8»3
9»4
10»■5

备机读取使用说明

设置读取节点

-- 0:Leader节点,1:Follower节点
SET persist tdsql_stale_read_role=1;

语句级别备机读取

操作与语句级别的闪回查询相同。

会话级别/事务级别备机读取

提供 session 变量tdsql_read_staleness_t,支持会话级别和事务级别的查询。
--查询当前数据
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
+----+-----+

set tdsql_read_staleness_t='-10'; #读取10秒前的数据

--插入新的数据
insert into t1 values (5,50);

--查看当前时间
select now();
+---------------------+
| now() |
+---------------------+
| 2025-02-16 17:57:50 |
+---------------------+

--查询当前数据
select * from t1; # 返回历史数据
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
+----+-----+

--等待一段时间
--查看当前时间
select now();
+---------------------+
| now() |
+---------------------+
| 2025-02-16 17:58:01 |
+---------------------+

--再次查询当前数据
select * from t1; # 返回新数据
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
| 5 | 50 |
+----+-----+
设置tdsql_read_staleness_t后,还可以开始事务查询数据。
--查询当前数据
select * from t1;
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
| 5 | 50 |
+----+-----+

--插入新的数据
insert into t1 values (6,60);

--开启事务
begin;
select * from t1; # 返回历史数据
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
| 5 | 50 |
+----+-----+
select sum(num) as total_num from t1;
+-----------+
| total_num |
+-----------+
| 150 |
+-----------+
rollback;

--等待一段时间
--开启事务
begin;
select * from t1; # 返回新数据
+----+-----+
| id | num |
+----+-----+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
| 5 | 50 |
| 6 | 60 |
+----+-----+
select sum(num) as total_num from t1;
+-----------+
| total_num |
+-----------+
| 210 |
+-----------+
rollback;

相关参数

参数名
参数范围
类型
默认值
取值范围
是否需重启
说明
tdsql_enable_stale_read
GLOBAL
Boolean
ON
ON/OFF
闪回查询功能的开关。
advance-global-earliest-snapshot-delay
GLOBAL
Integer
10
0~43200
MC 一侧用于调控闪回查询的可查询的时间范围,单位:秒。
此参数的值越大,闪回查询支持的历史数据查询时间越长,同时占用的存储空间和查询时长也可能增加。
tdsql_stale_read_role
GLOBAL
UINT
0
0/1
设置 Stale Read 路由访问的副本。
0:表示 Leader 节点。
1:表示 Follower 节点。

tdsql_read_staleness_t
SESSION
CHAR
''
-
设置 Stale Read 数据陈旧时间。示例:
set session tdsql_read_staleness_t='-3'
开启 Stale Read staleness 模式,读取数据的时间为当前物理时间前3秒。
注意:set session tdsql_read_staleness_t=''(空字符)表示关闭 Stale Read staleness 模式。