闪回

当系统 INI 参数 ENABLE_FLASHBACK 置为 1 时,闪回功能开启,可以使用闪回表或进行闪回查询。DM MPP 环境暂不支持闪回功能。

17.1 闪回表

闪回表是在数据库联机时,通过只回退对指定表及其相关对象所做的更改,将表里的数据回退到历史的某个时间点,而不需要执行传统的时间点恢复操作。比如回退到用户误删除数据之前的时间点,从而将误删除的数据恢复回来,在这个操作过程中,数据库仍然可用而且不需要额外的空间。

闪回表利用的是 UNDO 表空间里所记录的数据被改变前的值。因此,如果因保留时间超过了初始化参数 UNDO_RETENTION 所指定的值,从而导致闪回表时所需要的 UNDO 数据被其他事务覆盖的话,那么就不能将表中数据恢复到指定的时间了。

与介质恢复相比,闪回表在易用性、可用性和还原时间方面有明显的优势。

17.1.1 闪回表定义

语法格式:

FLASHBACK TABLE	[<模式名>.]<表名> {,[<模式名>.]<表名>} TO <SCN | LSN | TIMESTAMP> <expr> [ <ENABLE|DISABLE> TRIGGERS ] ;

参数

  1. < 模式名 > 指明该表属于哪个模式,缺省为当前模式;
  2. < 表名 > 指明被创建的基表名,基表名最大长度 128 字节;
  3. <expr> 指明闪回到的 LSN 值或 TIMESTAMP 值;
  4. <ENABLE|DISABLE> TRIGGERS 指定是否开启触发器,ENABLE 为开启触发器,DISABLE 为关闭触发器,不指定则默认为关闭。

图例

闪回表语句

闪回表.png

17.1.2 使用说明

  1. 使用闪回功能需要打开 dm.ini 中的 ENABLE_FLASHBACK 参数;
  2. 当前闪回表功能支持:批量闪回多个表、触发器的禁用与启用、DMDPC 环境(除使用 LOCAL 登录外)、DMDSC 环境;
  3. 当前闪回表功能不支持在 DM MPP 环境下使用;
  4. 闪回表利用的是 UNDO 表空间里记录的数据被改变前的值,只能闪回到 UNDO_RETENTION 指定值范围内的时间点;
  5. 用户必须具有 FLASHBACK ANY TABLE 系统权限或 FLASHBACK 对象权限
  6. 闪回表语句是作为单个事务处理来执行。同时闪回多个表时,必须成功闪回所有表,否则会回退整个事务。闪回作为 DDL 语句,开启自动提交时,闪回成功后会自动提交;
  7. 必须对要执行闪回操作的表启动行移动(分区表具有 MOVEMENT 功能的不能关闭,否则闪回可能会报错);
  8. 不会闪回受影响对象的统计信息;
  9. 闪回会保留所有现有的索引;
  10. 闪回中会正常检查约束条件,如果在闪回执行期间违反了任何约束条件,则会回滚闪回操作;
  11. 闪回不能跨越修改了表结构的 DDL。比如,在闪回数据之前,做过删除一个字段的操作,那么是无法闪回的;
  12. 不能对系统表、临时表、HUGE 表、内部辅助表、动态表等执行闪回表操作;
  13. DMDPC 环境下由于各节点的 SCN/LSN 不同,只支持闪回到时间点 TIMESTAMP;
  14. 限制重复闪回。闪回作为 DDL,对于同一个表,不允许再次闪回到上一次闪回之前的 LSN/TIMESTAMP。

17.1.3 使用示例

使用闪回功能需要先开启闪回参数 ENABLE_FLASHBACK。

ALTER SYSTEM SET 'ENABLE_FLASHBACK'=1;

例 1 闪回到指定 LSN,例子中的 LSN 需根据实际替换。

DROP TABLE T;
CREATE TABLE T(C1 INT);
INSERT INTO T SELECT LEVEL CONNECT BY LEVEL < 4;
COMMIT;
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

SELECT CUR_LSN FROM V$RLOG;

查询结果如下:

行号       CUR_LSN
---------- --------------------
1          366234

DELETE FROM T WHERE C1=3;
INSERT INTO T VALUES(4);
COMMIT;
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          4

FLASHBACK TABLE T TO LSN 366234; //366234为前面查询出的CUR_LSN值
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

例 2 闪回到指定 TIMESTAMP,例子中的 TIMESTAMP 需根据实际替换。

DROP TABLE T;
CREATE TABLE T(C1 INT);
INSERT INTO T SELECT LEVEL CONNECT BY LEVEL < 4;
COMMIT;
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

//由于V$LSN_TIME有3S延迟,对TO TIMESTAMP的闪回,这里延迟3S再进行操作
//查询当前时间(也可借助V$LSN_TIME)
SELECT SYSDATE;

查询结果如下:

行号       SYSDATE
---------- -------------------
1          2023-04-11 15:17:28

DELETE FROM T WHERE C1=3;
INSERT INTO T VALUES(4);
COMMIT;
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          4

//执行闪回操作,'2023-04-11 15:17:28'为前面查询出的SYSDATE,前面查询已考虑了3秒误差
FLASHBACK TABLE T TO TIMESTAMP '2023-04-11 15:17:28';
SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

例 3 同时闪回多个表,指定 LSN,例子中的 LSN 需根据实际替换。

DROP TABLE TT;
DROP TABLE T CASCADE;

CREATE TABLE T(C1 INT PRIMARY KEY);
CREATE TABLE TT(C2 INT, FOREIGN KEY (C2) REFERENCES T(C1));

INSERT INTO T SELECT LEVEL CONNECT BY LEVEL < 4;
INSERT INTO TT VALUES(2);
COMMIT;

SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

SELECT * FROM TT;

查询结果如下:

行号       C2
---------- -----------
1          2

SELECT CUR_LSN FROM V$RLOG;

查询结果如下:

行号       CUR_LSN
---------- --------------------
1          367479

DELETE FROM TT;
DELETE FROM T WHERE C1=2;
COMMIT;

SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          3

SELECT * FROM TT;

查询结果为:未选定行

//367479为前面查出的CUR_LSN
FLASHBACK TABLE T, TT TO LSN 367479;

SELECT * FROM T;

查询结果如下:

行号       C1
---------- -----------
1          1
2          2
3          3

SELECT * FROM TT;

查询结果如下:

行号       C2
---------- -----------
1          2

例 4 带触发器的表闪回时禁用触发器的表现,例子中的 LSN 需根据实际替换。

DROP TABLE T;
CREATE TABLE T(A INT,B INT);
INSERT INTO T VALUES(10,10);
INSERT INTO T VALUES(11,11);
COMMIT;

//在表上创建触发器
CREATE OR REPLACE TRIGGER TR
BEFORE DELETE ON T
BEGIN
  INSERT INTO T VALUES(111,111);   //替换动作
END;
/

SELECT * FROM T;

查询结果如下:

行号       A           B
---------- ----------- -----------
1          10          10
2          11          11

SELECT CUR_LSN FROM V$RLOG;   

查询结果如下:

行号       CUR_LSN
---------- --------------------
1          368114

INSERT INTO T VALUES(1,4);
COMMIT;
FLASHBACK TABLE T TO LSN 368114 DISABLE TRIGGERS;
SELECT * FROM T;

查询结果如下:

行号       A           B
---------- ----------- -----------
1          10          10
2          11          11

17.2 闪回查询

DM MPP 环境不支持闪回查询。数据守护环境下,备库不支持闪回查询。

DMDPC 环境下仅支持基于时间进行闪回查询,不支持基于 LSN 进行闪回查询。

17.2.1 闪回查询子句

闪回查询子句的语法,是在数据查询语句(参考第 4 章 数据查询语句)的基础上,为 FROM 子句增加了闪回查询子句。

语法格式

<闪回查询子句>::=
  WHEN <TIMESTAMP time_exp> | 
  AS OF <TIMESTAMP time_exp> |
  AS OF <SCN|LSN lsn>

参数

1.time_exp 一个日期表达式,一般用字符串方式表示

2.lsn 指定 LSN 值

图例

闪回查询子句

闪回查询子句.png

语句功能

用户通过闪回查询子句,可以得到指定表过去某时刻的结果集。指定条件可以为时刻或 LSN。

使用说明

  1. 闪回查询只支持普通表(包括加密表与压缩表)、水平分区表和堆表,不支持临时表、列存储表、外部表与视图;
  2. 闪回查询中 lsn 的值,可以通过查询动态视图 V$RLOG 或 V$LSN_TIME 来确定,也可以通过闪回版本查询(见下节)的伪列来确定;
  3. 由于视图 V$LSN_TIME 每三秒收集一次 LSN/TIME 映射关系,因此基于时间进行闪回查询时可能存在三秒的误差,如果需要进行精确度更高的闪回查询,建议基于 LSN 进行闪回查询。
  4. 当闪回表作为 DDL 时,对于同一个表,不允许基于对上一次闪回表的 LSN 或 TIMESTAMP 进行闪回查询。

举例说明

例 1 闪回查询特定时刻的 PERSON_TYPE 表。

查询 PERSON_TYPE 表。

  SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表

在 2012-01-01 12:22:49 时刻插入数据,并提交。

  INSERT INTO PERSON.PERSON_TYPE(NAME) VALUES('防损员');

  INSERT INTO PERSON.PERSON_TYPE(NAME) VALUES('保洁员');

  COMMIT;

  SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             防损员
6			 保洁员

使用闪回查询取得 2012-01-01 12:22:45 时刻的数据。此时刻在插入数据的操作之前,可见此时的结果集不应该有 2012-01-01 12:22:49 时刻插入的数据。

SELECT * FROM PERSON.PERSON_TYPE WHEN TIMESTAMP '2012-01-01 12:22:45';

SELECT * FROM PERSON.PERSON_TYPE AS OF TIMESTAMP '2012-01-01 12:22:45';

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表

在 2012-01-01 12:23:29 时刻删除数据,并提交。

  DELETE FROM PERSON.PERSON_TYPE WHERE PERSON_TYPEID > 5;

  COMMIT;

  SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             防损员

使用闪回查询得到删除前的数据。

SELECT * FROM PERSON.PERSON_TYPE WHEN TIMESTAMP '2012-01-01 12:23:00';

SELECT * FROM PERSON.PERSON_TYPE AS OF TIMESTAMP '2012-01-01 12:23:00';

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             防损员
6             保洁员

例 2 闪回查询指定 LSN 的 PERSON_TYPE 表。

查询 PERSON_TYPE 表。

  SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表

通过查询 V$RLOG 视图的 CUR_LSN 字段来获取当前 LSN 值。

SELECT CUR_LSN FROM V$RLOG;

查询结果如下:

行号     CUR_LSN
------- ---------------------
1       85233

删除 PERSON_TYPE 表中的一行数据,并提交。

DELETE FROM PERSON.PERSON_TYPE WHERE PERSON_TYPEID=4;

COMMIT;

SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理

通过删除操作之前的 LSN 值进行闪回查询得到删除前的数据。

SELECT * FROM PERSON.PERSON_TYPE AS OF SCN 85233;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表

17.2.2 闪回版本查询

INI 参数 UNDO_RETENTION 设置了事务提交后回滚页保持时间,缺省为 90 秒。因此,超出 UNDO_RETENTION 时间之外的过期闪回版本,无法被闪回查询到。

语法格式

  <闪回版本查询子句>::=VERSIONS BETWEEN <闪回版本查询条件>
  <闪回版本查询条件>::=TIMESTAMP <time_exp1> AND <time_exp2> | 
                     SCN|LSN <lsn1> AND <lsn2>

参数

1.time_exp 日期表达式,一般用字符串方式表示。<time_exp1> 表示起始时间,<time_exp2> 表示结束时间

2.lsn 指定 LSN 值。<lsn1> 表示起始 LSN,<lsn2> 表示结束 LSN

使用说明

  1. 闪回版本查询支持普通表(包括加密表与压缩表)、水平分区表和堆表,不支持临时表、列存储表、外部表与视图;
  2. 支持将表 17.2.1 中的伪列作为闪回版本查询的查询项,辅助获取精准的闪回查询信息。
表17.2.1 闪回版本查询支持的伪列
伪列 说明
VERSIONS_STARTTIME、VERSIONS_STARTSCN、VERSIONS_STARTTRXID 起始时间戳、起始 LSN、起始 TRXID
VERSIONS_ENDTIME、VERSIONS_ENDSCN、VERSIONS_ENDTRXID 提交时间戳、提交 LSN、提交 TRXID。如果该值为 NULL,表示行版本仍然是当前版本
VERSIONS_OPERATION 在行上的操作。I 表示 Insert、D 表示 Delete、U 表示 Update

图例

闪回版本查询

闪回版本查询.png

语句功能

用户通过闪回版本查询子句,可以得到指定表过去某个时间段内,事务导致记录变化的全部记录。指定条件可以为时刻或 LSN。

举例说明

例 1 闪回版本查询指定时间段内,PERSON_TYPE 表的记录变化。

查询 PERSON_TYPE 表。

SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             防损员

在 2021-12-28 10:05:05 时刻修改数据,并提交。

  UPDATE PERSON.PERSON_TYPE SET NAME='保安员' WHERE PERSON_TYPEID=5;

  COMMIT;

  UPDATE PERSON.PERSON_TYPE SET NAME='收银员' WHERE PERSON_TYPEID=5;

  COMMIT;

  SELECT * FROM PERSON.PERSON_TYPE;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             收银员

例 2 进行闪回版本查询,获得指定时间段内变化的记录。

SELECT VERSIONS_STARTSCN, VERSIONS_ENDSCN, NAME FROM PERSON.PERSON_TYPE VERSIONS BETWEEN TIMESTAMP '2021-12-28 10:05:05' AND SYSDATE;

查询结果如下:

VERSION_STARTSCN  PERSON_TYPEID   NAME
---------------- --------------  --------
41061            NULL			采购经理
41061            NULL			采购代表
41061            NULL			销售经理
41061            NULL			销售代表
41074            NULL	 		收银员
41071			41074		   保安员
41061		 	41071		   防损员

例 3 可以利用伪列 VERSION_STARTSCN 进行闪回查询得到修改前的数据。

SELECT * FROM PERSON.PERSON_TYPE AS OF SCN 41071;

查询结果如下:

PERSON_TYPEID NAME
------------- --------
1             采购经理
2             采购代表
3             销售经理
4             销售代表
5             保安员

17.2.3 闪回事务查询

闪回事务查询提供系统视图 V$FLASHBACK_TRX_INFO 供用户查看在事务级对数据库所做的更改。根据视图信息,可以确定如何还原指定事务或指定时间段内的修改。

使用说明

系统视图名为 V$FLASHBACK_TRX_INFO,定义如表 17.3.1 所示。

表17.3.1 系统视图V$FLASHBACK_TRX_INFO定义
列名 数据类型 说明
START_TRXID BIGINT 事务中第一个 DML 的 TRXID
START_TIMESTAMP DATETIME(6) 事务中第一个 DML 的时间戳
COMMIT_TRXID BIGINT 提交事务的 TRXID
COMMIT_TIMESTAMP DATETIME(6) 提交事务时的时间戳
LOGON_USER VARCHAR(256) 拥有事务的用户
UNDO_CHANGE# INTEGER 记录修改顺序序号
OPERATION CHAR(1) DML 操作类型。
D:删除;U:修改;I:插入;N:更新插入(专门针对 CLUSTER PRIMARY KEY 的插入); C:事务提交;P:预提交记录;O:default
TABLE_NAME VARCHAR(256) DML 修改的表
TABLE_OWNER VARCHAR(256) DML 修改表的拥有者
ROW_ID BIGINT DML 修改行的 ROWID
UNDO_SQL VARCHAR(3900) 撤销 DML 操作的 SQL 语句
COMMIT_LSN BIGINT 事务提交时的 LSN

举例说明

例 查询指定时间之后的事务信息,可为闪回查询操作提供参考。

  SELECT * FROM V$FLASHBACK_TRX_INFO WHERE COMMIT_TIMESTAMP > '2012-01-01 12:00:00';
微信扫码
分享文档
扫一扫
联系客服