SELECT: FLASHBACK

说明

按照实现方式主要分为:基于回滚段进行闪回查询和基于归档日志进行闪回查询

  • 基于回滚段进行闪回查询:使用回滚段的数据构造所需的数据
  • 基于归档日志进行闪回查询:逆向扫描归档日志,构造出历史版本数据或者指定版本的数据

按照闪回功能主要分为:闪回版本查询和闪回时间点查询

  • 闪回版本查询:根据归档/undo日志的数据模拟回滚操作构造出表中历史数据的版本
  • 闪回时间点查询:根据undo日志的数据构造出指定版本的数据

语法

select_flashback ::=

version_between ::=

as_of ::=

参数

expr

当选择 TIMESTAMP 参数时,expr 对应的为时间戳; 当选择 SCN 参数时,expr 对应的为SCN的数值或表达式。

version_between

闪回版本查询,查询表中从BETWEEN指定的SCN/TIMESTAMP到AND指定的SCN/TIMESTAMP之间的所有数据版本,当指定的SCN范围为[MINVALUE-MAXVALUE]会构造出这个表自创建以来的所有数据版本。

as_of

闪回时间点查询,根据AS OF指定的SCN/TIMESTAMP构造出对应时间点的数据。

相关配置参数:

  • ENABLE_FLASHBACK_QUERY_USE_ARCHIVELOG(默认为FALSE):是否基于归档日志进行闪回查询。
  • ENABLE_FLASHBACK_QUERY_LOB_AS_NULL(默认为FALSE):是否在闪回查询中将大对象直接返回为NULL,当设置为FALSE时遇到大对象或用到大对象的text,xml类型会报错。
  • FLASHBACK_MEM(默认 1GB):在基于归档日志进行闪回查询时最多可以使用多大的内存空间。

方式对比:

  • 基于回滚段进行闪回时间点查询可以充分利用现有的多版本机制,性能较好,缺点是受限于回滚段重用机制,只能查询很短时间之内的数据。神通数据库目前基于回滚段的闪回查询只支持闪回时间点查询。
  • 基于归档日志方式进行闪回查询的好处是只要有归档日志,可以查询很长时间之内的数据,缺点是性能较差,并且需要占用内存和临时表空间(要查询的版本越旧,需要的内存和临时表空间越多)。

相关伪列:

符号 说明
VERSIONS_STARTSCN 本历史行的生成SCN
VERSIONS_ENDSCN 本历史行的消失SCN
VERSIONS_STARTTIME 本历史行的生成时间
VERSIONS_ENDTIME 本历史行的消失时间
VERSIONS_XID 本历史行的操作事务号
VERSIONS_OPERATION 生成本历史行的操作

注解

特别说明:

  • 闪回查询可能会遇到“快照过旧,当前索引有过空页面清理操作,因此无法处理清理操作之前索引相关的事务”这种报错。

原因是:神通数据库支持自动清理索引空页面,并且无法再恢复这些页面的历史版本,闪回查询无法对这些页面的修改进行进行回滚

解决方法:避免闪回查询走索引扫描。例如指定 hint。

  • 基于归档日志的闪回查询,可能会遇到“闪回查询构造快照页面失败”这种报错。

原因是:从要闪回的时间点到当前时刻,已产生的日志量越大,闪回时需要逆向扫描的日志就越多,这个时间如果超过了数据库配置参数 UNDO_RETENTION 的值,可能导致上述报错。

解决方法:通过 SET 命令,将参数 UNDO_RETENTION 的值修改成比报错语句的执行时间更大的值,重新进行闪回查询。并在查询成功后,再将参数值改回为原来的值。

示例

示例1: 按照时间点进行闪回查询

--  清理环境
DROP TABLE tab1 CASCADE;

--  创建表
CREATE TABLE tab1 (a INT, b INT);

--  查看当前时间
SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss') FROM DUAL;

       TO_CHAR
---------------------
 2019-11-29 15:59:28
(1 row)

--  插入数据
INSERT INTO tab1 VALUES(1, 10);
INSERT INTO tab1 VALUES(2, 20);

--  查看当前时间
SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss') FROM DUAL;

       TO_CHAR
---------------------
 2019-11-29 16:01:36
(1 row)

--  普通查询
SELECT * FROM tab1;

 A | B
---+----
 1 | 10
 2 | 20
(2 rows)

--  按时间点闪回查询
SELECT * FROM tab1 AS OF TIMESTAMP '2019-11-29 15:59:28';

 A | B
---+---
(0 rows)

SELECT * FROM tab1 AS OF TIMESTAMP '2019-11-29 16:01:36';

 A | B
---+----
 1 | 10
 2 | 20
(2 rows)


--  查询一段时间内的操作记录
SELECT VERSIONS_STARTSCN, VERSIONS_ENDSCN, VERSIONS_STARTTIME, VERSIONS_ENDTIME, VERSIONS_XID::BINARY(8)::INT8, VERSIONS_OPERATION, ROWID, * FROM tab1 VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE;

 VERSIONS_STARTSCN | VERSIONS_ENDSCN | VERSIONS_STARTTIME  | VERSIONS_ENDTIME |   VERSIONS_XID    | VERSIONS_OPERATION |      ROWID      | A | B
-------------------+-----------------+---------------------+------------------+-------------------+--------------------+-----------------+---+----
              3305 |                 | 2019-11-29 16:01:10 |                  | 32369678156300289 | I                  |           17698 | 1 | 10
              3306 |                 | 2019-11-29 16:01:10 |                  | 32369682451267585 | I                  | 281474976728354 | 2 | 20
(2 rows)

--  删除表
DROP TABLE tab1;