
# 闪回查询
#### 背景信息
闪回查询可以查询过去某个时间点表的某个snapshot数据，这一特性可用于查看和逻辑重建意外删除或更改的受损数据。闪回查询基于MVCC多版本机制，通过检索查询旧版本，获取指定老版本数据。
#### 前提条件
整体方案分为三部分：旧版本保留、快照的维护和旧版本检索。旧版本保留：新增undo_retention_time配置参数，用来设置旧版本保留的时间，超过该时间的旧版本将被回收清理，若使用闪回查询则需将该参数设置为大于0的值，请联系管理员修改。
#### 语法
```
{[ ONLY ] table_name [ * ] [ partition_clause ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
[ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ]
[TIMECAPSULE { TIMESTAMP | CSN } expression ]
|( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
|with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
|function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ]
|function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
|from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]}
```
语法树中"TIMECAPSULE {TIMESTAMP \| CSN} expression"为闪回功能新增表达方式，其中TIMECAPSULE表示使用闪回功能，TIMESTAMP以及CSN表示闪回功能使用具体时间点信息或使用CSN（commit sequence number）信息。
#### 参数说明
- TIMESTAMP
  - 指要查询某个表在TIMESTAMP这个时间点上的数据，TIMESTAMP指一个具体的历史时间。
   
 
- CSN
  - 指要查询整个数据库逻辑提交序下某个CSN点的数据，CSN指一个具体逻辑提交时间点，数据库中的CSN为写一致性点，每个CSN代表整个数据库的一个一致性点，查询某个CSN下的数据代表SQL查询数据库在该一致性点的相关数据。
   
备注：使用时间点进行闪回时，可能会有3s的误差。想要闪回到精确的操作点，需要使用CSN进行闪回。GTM-Free模式下没有全局一致性csn点，暂时不支持以csn的方式进行闪回。
#### 使用示例
- 示例（需将undo_retention_time参数设置为大于0的值）：
  ```
  gaussdb=# DROP TABLE IF EXISTS "public".flashtest;
  NOTICE:  table "flashtest" does not exist, skipping
  DROP TABLE
  --创建表flashtest。
  gaussdb=# CREATE TABLE "public".flashtest (col1 INT,col2 TEXT) with(storage_type=ustore);
  NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'col1' as the distribution column by default.
  HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
  CREATE TABLE
  --查询csn。
  gaussdb=# SELECT int8in(xidout(next_csn)) FROM gs_get_next_xid_csn();
    int8in  
  ----------
   79351682
   79351682
   79351682
   79351682
   79351682
   79351682
  (6 rows)
  --查询当前时间戳。
  gaussdb=# SELECT now();
                now              
  -------------------------------
   2023-09-13 19:35:26.011986+08
  (1 row)
  --插入数据。
  gaussdb=# INSERT INTO flashtest VALUES(1,'INSERT1'),(2,'INSERT2'),(3,'INSERT3'),(4,'INSERT4'),(5,'INSERT5'),(6,'INSERT6');
  INSERT 0 6
  gaussdb=# SELECT * FROM flashtest;
   col1 |  col2   
  ------+---------
      3 | INSERT3
      1 | INSERT1
      2 | INSERT2
      4 | INSERT4
      5 | INSERT5
      6 | INSERT6
  (6 rows)
  --闪回查询某个csn处的表。
  gaussdb=# SELECT * FROM flashtest TIMECAPSULE CSN 79351682;
   col1 | col2 
  ------+------
  (0 rows)
  gaussdb=# SELECT * FROM flashtest;
   col1 |  col2   
  ------+---------
      1 | INSERT1
      2 | INSERT2
      4 | INSERT4
      5 | INSERT5
      3 | INSERT3
      6 | INSERT6
  (6 rows)
  --闪回查询某个时间戳处的表。
  gaussdb=# SELECT * FROM flashtest TIMECAPSULE TIMESTAMP '2023-09-13 19:35:26.011986';
   col1 | col2 
  ------+------
  (0 rows)
  gaussdb=# SELECT * FROM flashtest;
   col1 |  col2   
  ------+---------
      1 | INSERT1
      2 | INSERT2
      4 | INSERT4
      5 | INSERT5
      3 | INSERT3
      6 | INSERT6
  (6 rows)
  --闪回查询某个时间戳处的表。
  gaussdb=# SELECT * FROM flashtest TIMECAPSULE TIMESTAMP to_timestamp ('2023-09-13 19:35:26.011986', 'YYYY-MM-DD HH24:MI:SS.FF');
   col1 | col2 
  ------+------
  (0 rows)
  --闪回查询某个csn处的表，并对表进行重命名。
  gaussdb=# SELECT * FROM flashtest AS ft TIMECAPSULE CSN 79351682;
   col1 | col2 
  ------+------
  (0 rows)
  gaussdb=# DROP TABLE IF EXISTS "public".flashtest;
  DROP TABLE
  ```
  
 
