集群单表闪回
集群单表闪回¶
集群单表闪回允许将集群单个用户表中数据恢复到某个指定时间的状态。能够在短时间内恢复对表的误操作(DML或部分DDL),为数据库的数据恢复提供更加便捷的途径。
配置参数¶
-
shared_preload_libraries 设置shared_preload_libraries = 'sdtrashcan',加载此功能需要用的库。
-
flashback_mode 设置flashback_mode = 'mod',来保证不涉及删除表文件的事务可以被闪回,不必重启服务,但需要重新加载配置参数。 设置flashback_mode = 'all',来保证所有事务可以被闪回,不必重启服务,但需要重新加载配置参数。
-
autovacuum 控制是否使用autovacuum功能,设置autovacuum = 'off',关闭该功能。
说明 第一个参数需要重启服务才能生效。
集群单表闪回¶
功能描述:
集群单表闪回允许将表中数据恢复到某一指定时间戳时的状态。
工作原理:
在SeaboxMPP中,根据mvcc原理,删除或者更新元组并没有立即删除旧数据,而只是标记为已删除,在vacuum清理之前,这些数据还存在page页中,根据元组可见性,通过闪回查询过去某个时间点或某个事务可见的数据,然后恢复到表中。
使用注意事项:
- 闪回SQL中的时间戳或集群事务号,通过调用函数sd_record_timestamp_gxid存储到系统表sd_timestamp_gxid中
- 用户可以手动执行或者启用定时job来调用函数sd_record_timestamp_gxid
seaboxsql=# select * from sd_record_timestamp_gxid(); time | gxid | dboid ------------------------+--------+------- 2023-06-06 14:34:26+08 | 214016 | 13841 (1 row)
说明
- gxid表示当前时刻(time)下一个开始的集群事务的事务号,即该集群事务号(gxid)之前的事务号已经被使用
-
从闪回结果来看,gxid所对应的事务是不可见的
-
指定时间点集群单表闪回
功能描述:
使用FLASHBACK语句将表闪回至某个过去时间点的状态。
集群单表闪回语法:
FLASHBACK TABLE table_name TIMESTAMP expression
示例:
- 闪回DML操作
seaboxsql=# CREATE TABLE test(a int, b text) distributed by (a);
CREATE TABLE
seaboxsql=# create index idx on test(a);
CREATE INDEX
seaboxsql=# insert into test select g, g||'abcd' from generate_series(1, 20)g;
INSERT 0 20
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-06-06 14:34:26+08 | 214016 | 13841
(1 row)
seaboxsql=# insert into test select g, g||'abcd' from generate_series(21, 40)g;
INSERT 0 20
seaboxsql=# select * from sd_timestamp_gxid ;
time | gxid | dboid
------------------------+--------+-------
2023-06-06 14:34:26+08 | 214016 | 13841
(1 row)
seaboxsql=# flashback table test timestamp '2023-06-06 14:34:26';
FLASHBACK TABLE
seaboxsql=# select count(*) from test;
count
-------
20
(1 row)
-
闪回DML与带时间戳的VACUUM
-
vacuum timestamp阻止了删除的数据被vacuum
seaboxsql=# create table t1(a int, b varchar(20)) distributed by(a);
CREATE TABLE
seaboxsql=# insert into t1 select i, 'abcd' from generate_series(1, 10)i;
INSERT 0 10
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-11-09 10:57:59+08 | 160034 | 14761
(1 row)
seaboxsql=# delete from t1 where a < 6;
DELETE 5
seaboxsql=# vacuum before '2023-11-09 10:57:59' t1;
VACUUM
seaboxsql=# flashback table t1 timestamp '2023-11-09 10:57:59';
FLASHBACK TABLE
seaboxsql=# select * from t1;
a | b
----+------
1 | abcd
6 | abcd
9 | abcd
10 | abcd
5 | abcd
7 | abcd
8 | abcd
2 | abcd
3 | abcd
4 | abcd
(10 rows)
- vacuum timestamp 使delete的数据被vacuum
seaboxsql=# create table t1(a int, b varchar(20)) distributed by(a);
CREATE TABLE
seaboxsql=# insert into t1 select i, 'abcd' from generate_series(1, 10)i;
INSERT 0 10
seaboxsql=# delete from t1 where a < 6;
DELETE 5
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-11-09 11:01:40+08 | 160041 | 14761
(1 row)
seaboxsql=# vacuum before '2023-11-09 11:01:40' t1;
VACUUM
seaboxsql=# flashback table t1 timestamp '2023-11-09 11:01:40';
FLASHBACK TABLE
seaboxsql=# select * from t1;
a | b
----+------
6 | abcd
9 | abcd
10 | abcd
7 | abcd
8 | abcd
(5 rows)
- 闪回DDL操作
seaboxsql=# CREATE TABLE test(a int, b text) distributed by (a);
CREATE TABLE
seaboxsql=# create index idx on test(a);
CREATE INDEX
seaboxsql=# insert into test select g, g||'abcd' from generate_series(1, 20)g;
INSERT 0 20
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-06-06 14:57:10+08 | 214016 | 13841
(1 row)
seaboxsql=# insert into test select g, g||'abcd' from generate_series(21, 40)g;
INSERT 0 20
seaboxsql=# drop table test;
DROP TABLE
seaboxsql=# select * from sd_timestamp_gxid ;
time | gxid | dboid
------------------------+--------+-------
2023-06-06 14:57:10+08 | 214016 | 13841
(1 row)
seaboxsql=# flashback table test timestamp '2023-06-06 14:57:10';
FLASHBACK TABLE
seaboxsql=# select count(*) from test;
count
-------
20
(1 row)
集群单表查询闪回¶
闪回查询允许查询过去时间点数据,或过去时间段数据变化。能够在短时间内恢复错误操作等造成的数据错误问题,恢复错误的DML操作,为数据库的数据恢复提供更加便捷的途径。
功能描述:
闪回查询允许查询过去某个时间点的所有数据。
工作原理:
在SeaboxSQL中,根据mvcc原理,删除或者更新元组并没有立即删除旧数据,而只是标记为已删除,在vacuum清理之前,这些数据还存在page页中,根据元组可见性,闪回查询过去某个时间点或某个事务可见的数据。 使用系统表sd_timestamp_gxid记录时间戳及其集群事务号。
- 指定时间点闪回查询
功能描述:
在SELECT中使用FLASHBACK子句指定过去时间点查询。
闪回语法:
SELECT column_name[, …]
FROM table_name
[FLASHBACK TIMESTAMP expression]
[WHERE condition]
其中, FLASHBACK用于指定闪回查询时查询的时间点。时间为timestamp类型,时间格式为“YYYY-MM-DD HH24:MI:SS”。
示例1:
-
事务操作
seaboxsql=# CREATE TABLE test(a int, b text) distributed by (a); CREATE TABLE seaboxsql=# insert into test select g, g||'abcd' from generate_series(1, 10)g; INSERT 0 10 seaboxsql=# select * from sd_record_timestamp_gxid(); time | gxid | dboid ------------------------+--------+------- 2023-06-07 08:48:43+08 | 214016 | 13841 (1 row) seaboxsql=# update test set a=a*10; UPDATE 10 seaboxsql=# select * from sd_record_timestamp_gxid(); time | gxid | dboid ------------------------+--------+------- 2023-06-07 08:48:52+08 | 214016 | 13841 (1 row) seaboxsql=# update test set a=a*10; UPDATE 10 seaboxsql=# select * from sd_record_timestamp_gxid(); time | gxid | dboid ------------------------+--------+------- 2023-06-07 08:48:58+08 | 214016 | 13841 (1 row) seaboxsql=# update test set a=a*10; UPDATE 10 seaboxsql=# select * from test; a | b -------+-------- 7000 | 7abcd 8000 | 8abcd 6000 | 6abcd 2000 | 2abcd 1000 | 1abcd 5000 | 5abcd 9000 | 9abcd 3000 | 3abcd 4000 | 4abcd 10000 | 10abcd (10 rows)
-
指定时间戳闪回查询
seaboxsql=# select * from test flashback timestamp '2023-06-07 08:48:52'; a | b -----+-------- 10 | 1abcd 100 | 10abcd 70 | 7abcd 80 | 8abcd 60 | 6abcd 90 | 9abcd 20 | 2abcd 30 | 3abcd 40 | 4abcd 50 | 5abcd (10 rows) seaboxsql=# select * from test flashback timestamp '2023-06-07 08:48:58'; a | b ------+-------- 600 | 6abcd 200 | 2abcd 100 | 1abcd 700 | 7abcd 800 | 8abcd 500 | 5abcd 1000 | 10abcd 900 | 9abcd 300 | 3abcd 400 | 4abcd (10 rows)
-
指定事务号闪回查询
功能描述:
在SELECT中使用FLASHBACK子句指定事务号查询。
闪回语法:
SELECT column_name[, …]
FROM table_name
[FLASHBACK XID expression]
[WHERE condition]
示例2:
- 指定事务号闪回查询
seaboxsql=# select * from test flashback xid 114011; a | b -----+-------- 10 | 1abcd 100 | 10abcd 70 | 7abcd 80 | 8abcd 60 | 6abcd 90 | 9abcd 20 | 2abcd 30 | 3abcd 40 | 4abcd 50 | 5abcd (10 rows) seaboxsql=# select * from test flashback xid 114012; a | b ------+-------- 700 | 7abcd 800 | 8abcd 500 | 5abcd 1000 | 10abcd 900 | 9abcd 300 | 3abcd 400 | 4abcd 600 | 6abcd 200 | 2abcd 100 | 1abcd (10 rows)
闪回版本查询¶
功能描述:
闪回版本查询返回在指定时间间隔或事务号间隔内的所有版本。
工作原理:
与闪回查询同理,返回一个时间段内所有的版本。
- 指定时间点闪回版本查询
功能描述:
在 SELECT 中使用 FLASHBACK BETWEEN 子句指定时间点查询。
闪回语法:
SELECT column_name[, …]
FROM table_name
[FLASHBACK BETWEEN
TIMESTAMP expression AND expression]
WHERE condition
seaboxsql=# select * from test flashback between timestamp '2023-06-07 08:48:52' and '2023-06-07 08:48:58';
a | b
------+--------
10 | 1abcd
100 | 10abcd
600 | 6abcd
200 | 2abcd
100 | 1abcd
70 | 7abcd
80 | 8abcd
60 | 6abcd
90 | 9abcd
700 | 7abcd
800 | 8abcd
500 | 5abcd
1000 | 10abcd
20 | 2abcd
30 | 3abcd
40 | 4abcd
50 | 5abcd
900 | 9abcd
300 | 3abcd
400 | 4abcd
(20 rows)
- 指定事务号闪回版本查询
功能描述:
在SELECT中使用FLASHBACK BETWEEN子句指定事务号查询。
闪回语法:
SELECT column_name[, …]
FROM table_name
[FLASHBACK BETWEEN
XID expression AND expression]
WHERE condition
-
FLASHBACK BETWEEN 用于指定闪回版本查询时查询的事务号段。
-
示例 1
seaboxsql=# select * from test flashback between xid 114011 and 114012;
a | b
------+--------
20 | 2abcd
30 | 3abcd
40 | 4abcd
50 | 5abcd
900 | 9abcd
300 | 3abcd
400 | 4abcd
10 | 1abcd
100 | 10abcd
600 | 6abcd
200 | 2abcd
100 | 1abcd
70 | 7abcd
80 | 8abcd
60 | 6abcd
90 | 9abcd
700 | 7abcd
800 | 8abcd
500 | 5abcd
1000 | 10abcd
(20 rows)
- 示例 2
在同一个事务中对一行更新多次,只显示最后一次提交的版本。
seaboxsql=# CREATE TABLE test(a int, b text) distributed by (a);
CREATE TABLE
seaboxsql=# insert into test select g, g||'abcd' from generate_series(1, 10)g;
INSERT 0 10
seaboxsql=#
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-06-07 09:13:34+08| 214016 | 13841
(1 row)
seaboxsql=#
seaboxsql=# begin;
BEGIN
seaboxsql=# update test set a=a*10;
UPDATE 10
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-06-07 09:13:35+08 | 214016 | 13841
(1 row)
seaboxsql=# update test set a=a*10;
UPDATE 10
seaboxsql=# commit;
COMMIT
seaboxsql=# select * from sd_record_timestamp_gxid();
time | gxid | dboid
------------------------+--------+-------
2023-06-07 09:13:46+08 | 214016 | 13841
(1 row)
seaboxsql=# select * from test flashback between xid 114021 and 114022;
a | b
------+--------
2 | 2abcd
3 | 3abcd
4 | 4abcd
7 | 7abcd
8 | 8abcd
700 | 7abcd
800 | 8abcd
500 | 5abcd
1000 | 10abcd
5 | 5abcd
6 | 6abcd
9 | 9abcd
10 | 10abcd
600 | 6abcd
200 | 2abcd
100 | 1abcd
1 | 1abcd
900 | 9abcd
300 | 3abcd
400 | 4abcd
(20 rows)
注意事项¶
目前闪回查询功能只能对DML(insert、 update 和 delete)操作进行闪回查询,对于DDL truncate对表的操作,目前闪回查询还不支持。除此之外,闪回查询也不支持表结构做出的修改操作。