Oracle闪回技术

(一)闪回技术概要

闪回技术是数据库备份与恢复的重要补充手段,主要包括以下7种特性:

特性 原理 数据库支持
闪回查询
(Flashback Query)
利用undo表空间中的回退信息,查询过去某个时刻或SCN时表中数据的快照 Undo表空间配置
闪回版本查询
(Flashback Version Query)
利用undo表空间中的回退信息,查询过去某个时间段或某个SCN段内数据的变化情况 Undo表空间配置
闪回事务查询
(Flashback Transaction Query)
利用undo表空间中的回退信息,查询过去某个事务或所有事务在过去一段时间内对数据库所做的修改 Undo表空间配置
闪回表
(Flashback Table)
利用undo表空间中的信息,将表中的数据恢复到过去某个时间点或SCN时的状态 Undo表空间支持
闪回删除
(Flashback Drop)
利用“回收站功能”,将表及关联对象恢复到删除以前的状态 回收站
闪回数据库
(Flashback Database)
利用存储在快速恢复区(Flashback Recovery Area)的闪回日志(Flashback log),将数据库恢复到过去某个时刻或某个SCN 快速恢复区
闪回数据归档
(Flashback Data Archive)
利用保存在一个或多个表空间中的数据变化信息,查询过去某个时刻或SCN值时数据库表中数据的快照。 一个或多个闪回数据归档区

接下来一一学习。

 

(二)闪回查询

(1)主要功能

返回已经丢失或被误操作删除的数据在操作之前的快照。

(2)Undo表空间设置

与undo表空间相关的参数主要是下面三个:

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_management                      string      AUTO
undo_retention                       integer     900
undo_tablespace                      string      UNDOTBS1

①   undo_management:设置undo表空间的管理模式,有自动和手动管理两种方式,默认自动管理undo表空间;

②   undo_retention:设置保留时间,我们可以对其修改:

SQL > ALTER SYSTEM SET UNDO_RETENTION = 86400;  --修改为24小时

值得注意的是,undo_retention是一个“软设置”,数据库会尽量给你保留24小时,但是假如undo表空间不够用,数据是不会保留24小时的。

如果必须要保留24小时,可以启用Undo表空间的retention guarantee,保证过期的数据才能被删除,设置如下:

SQL > ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;

③   undo_tablespace:指明所使用的undo表空间

(3)闪回查询语法:

闪回查询是通过AS OF关键字实现的,具体如下:

SELECT column_name FROM table_name
AS OF SCN|TIMESTAMP expression
[WHERE condition];

其中,scn与timestamp是一一对应的,可以通过函数TIMESTAMP_TO_SCN(timestamp)和SCN_TO_TIMESTAMP(scn)来转换。

(4)例子1、通过timestamp来闪回查询用户所做操作。

16:59:48 SQL> create table test01
           2  (
           3      id        number(5),
           4      name      varchar(20),
           5      salary    number(5)
           6  );

17:02:52 SQL> insert into test01 values(1,'lijiaman',1000);
17:02:52 SQL> insert into test01 values(2,'liudedong',2000);
17:03:52 SQL> update test01 set salary = 1200 where id = 1;
17:04:59 SQL> update test01 set salary = 1400 where id = 1;
17:06:06 SQL> update test01 set salary = 1600 where id = 1;
17:07:04 SQL> delete from test01 where id = 2;

对于整个过程,我们可以使用下图来表示:

接下来,我们使用闪回查询技术查看数据:

-- 查看表中目前数据,只有一行
17:21:46 SQL> select * from test01;         
    ID NAME                 SALARY
------ -------------------- ------
     1 lijiaman               1600
     
-- 查看17:07:00的数据,此时还未删除数据,有2行,且id=1的salary是1600        
17:46:26 SQL> select * from test01 as of timestamp to_timestamp('2017-10-07 17:07:00','yyyy-mm-dd hh24:mi:ss');
    ID NAME                 SALARY
------ -------------------- ------
     1 lijiaman               1600
     2 liudedong              2000

-- 查看17:06:00的数据,此时id=1的salary还是1400 
17:54:28 SQL> select * from test01 as of timestamp to_timestamp('2017-10-07 17:06:00','yyyy-mm-dd hh24:mi:ss');
    ID NAME                 SALARY
------ -------------------- ------
     1 lijiaman               1400
     2 liudedong              2000

-- 查看17:04:00的数据,此时id=1的salary还是1200 
17:54:57 SQL> select * from test01 as of timestamp to_timestamp('2017-10-07 17:04:00','yyyy-mm-dd hh24:mi:ss');
    ID NAME                 SALARY
------ -------------------- ------
     1 lijiaman               1200
     2 liudedong              2000

-- 查看17:03:00的数据,此时id=1的salary还是1000 
17:55:14 SQL> select * from test01 as of timestamp to_timestamp('2017-10-07 17:03:00','yyyy-mm-dd hh24:mi:ss');
    ID NAME                 SALARY
------ -------------------- ------
     1 lijiaman               1000
     2 liudedong              2000 

-- 查看17:02:00的数据,此时还未向数据库插入数据 
17:55:20 SQL> select * from test01 as of timestamp to_timestamp('2017-10-07 17:02:00','yyyy-mm-dd hh24:mi:ss');
    ID NAME                 SALARY
------ -------------------- ------

 

(三)闪回版本查询

(1)主要功能

闪回版本提供了审计行数据变化的功能,可以跟踪一条记录在一段时间内的变化情况,即一条记录的多个提交版本信息(一个事物对一条记录的操作结果视为该记录的一个版本),从而为行级数据的追踪提供了可能。

(2)闪回版本查询语法
SELECT column_name[,…] FROM table_name 
VERSIONS BETWEEN SCN|TIMESTAMP MINVALUE|expression AND 
MAXVALUE | expression
[ AS OF SCN | TIMESTAMP expression ]
WHERE condition

参数说明:

--VERSIONS BETWEEN:用于指定闪回查询所要求的时间段或SCN段;

--AS OF:用于指定闪回查询时查询的目标时刻或目标SCN值;

 

在闪回查询的目标列中,可以使用以下伪列来返回行的版本信息:

--VERSIONS_STARTTIME:基于时间的版本有效范围的下界,可以理解为某个版本的开始时间,下亦相同;

--VERSIONS_ENDTIME:基于时间的版本有效范围的上界;

--VERSIONS_STARTSCN:基于SCN的版本有效范围的下界;

--VERSIONS_ENDSCN:基于SCN的版本有效范围的上界;

--VERSIONS_XID:操作的事物ID;

--VERSIONS_OPERATION:执行操作的类型,I:insert,D:delete,U:update

(3)例子2、版本闪回查询测试
20:06:51 SQL> create table test02
           2  (
           3      id        number(5),
           4      name      varchar(20),
           5      salary    number(5)
           6  );

20:09:23 SQL> insert into test02 values(1,'lijiaman',1000);           --事物1:第一次数据插入
20:09:23 SQL> insert into test02 values(2,'liudedong',2000);
20:09:23 SQL> commit;
20:10:09 SQL> update test02 set salary = 1100 where id = 1;
20:10:09 SQL> update test02 set salary = 1200 where id = 1;           --事物2:这里对同一行数据在同一个事物中更新了2次
20:10:09 SQL> commit;
20:11:10 SQL> update test02 set salary = 1400 where id = 1;           --事物3:再次数据更新
20:11:10 SQL> commit;
20:12:11 SQL> update test02 set salary = 1600 where id = 1;           --事物4:再次数据更新 
20:12:11 SQL> commit;
20:13:09 SQL> delete from test02 where id = 2;
20:13:09 SQL> commit;

接下来,我们通过闪回事物查询来看一下id=1的事物记录

20:15:27 SQL> select
           2    versions_xid,
           3    versions_starttime,
           4    versions_endtime,
           5    versions_operation,
           6    salary
           7  from
           8    test02
           9  versions between timestamp minvalue and maxvalue
          10  where
          11    id = 1;
 
VERSIONS_XID     VERSIONS_STARTTIME        VERSIONS_ENDTIME          VERSIONS_OPERATION SALARY
---------------- ------------------------  ------------------------- ------------------ ------
0300080046030000 07-10月-17 08.12.09 下午                                  U                  1600             --事物4:再次数据更新
07001A006D020000 07-10月-17 08.11.09 下午  07-10月-17 08.12.09 下午     U                  1400             --事物3:再次数据更新
070019006C020000 07-10月-17 08.10.03 下午  07-10月-17 08.11.09 下午     U                  1200             --事物2:这里执行了2次更新,很明显,第一次更新未记录
0400090080020000 07-10月-17 08.09.27 下午  07-10月-17 08.10.03 下午     I                  1000             --事物1:第一次数据插入

 

(四)闪回事物查询

(1)主要功能

闪回事务查询可以返回在一个特定事务中行的历史数据及与事务相关的元数据,或返回一个时间段内所有事务的操作结果及事务的元数据。

(2)日志追加功能

在Oracle 11g中,为了记录事务操作的详细信息,需要启动数据库的日志追加功能。

查看是否开启补充日志功能:

SQL> select supplemental_log_data_min from v$database;

SUPPLEMENTAL_LOG_DATA_MIN
-------------------------
NO

执行以下语句,开启数据库的日志追加功能:

SQL > ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

如果要禁用日志追加功能,可以使用下面的命令:

SQL > ALTER DATABASE DROP SUPPLEMENTAL LOG DATA;

(3)执行闪回事务查询

执行闪回事务查询要查询静态数据字典FLASHBACK_TRANSACTION_QUERY,该视图结构如下:

SQL> desc flashback_transaction_query;

Name             Type            Comments                                 
---------------- --------------  -----------------------------------------
XID              RAW(8)          事务ID
START_SCN        NUMBER          事务开始的SCN
START_TIMESTAMP  DATE            事务开始的时间戳
COMMIT_SCN       NUMBER          事务提交的SCN
COMMIT_TIMESTAMP DATE            事务提交的时间戳
LOGON_USER       VARCHAR2(30)    执行事物的数据库用户
UNDO_CHANGE#     NUMBER          撤销的SCN
OPERATION        VARCHAR2(32)    执行的操作类型
TABLE_NAME       VARCHAR2(256)   表名
TABLE_OWNER      VARCHAR2(32)    表的属主
ROW_ID           VARCHAR2(19)    行的ROWID
UNDO_SQL         VARCHAR2(4000)  撤销该事物的SQL

(4)例子3、执行闪回事物查询

--第一步:开启追加日志
SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
NO

SQL> alter database add supplemental log data;

--第二步:创建测试表test06
--21:19:34
create table test06
(
    id        number(5),
    name      varchar(20),
    salary    number(5)
);

--21:20:27
insert into test06 values(1,'lijiaman',1000);               --事物1:第一次数据插入20:09:23 SQL> insert into test02 values(2,'liudedong',2000);
commit;

--21:21:23 
update test06 set salary = 1100 where id = 1;
update test06 set salary = 1200 where id = 1;           --事物2:这里对同一行数据在同一个事物中更新了2次
commit;

--21:22:12 
update test06 set salary = 1400 where id = 1;           --事物3:再次数据更新
commit;


--第三步:执行闪回事物查询
--闪回事物查询通常与闪回版本查询一起使用

--先看闪回版本查询结果
select 
  versions_xid,
  versions_starttime,
  versions_endtime,
  versions_operation,
  id,
  name,
  salary
from
  test06
versions between timestamp minvalue and maxvalue
where 
  id = 1;

VERSIONS_XID     VERSIONS_STARTTIME     VERSIONS_ENDTIME       VERSIONS_OPERATION     ID NAME                 SALARY
---------------- ---------------------- ---------------------- ------------------ ------ -------------------- ------
060014002A040000 10-OCT-17 09.22.15 PM                         U                       1 lijiaman               1400
05001C00F7040000 10-OCT-17 09.21.30 PM  10-OCT-17 09.22.15 PM  U                       1 lijiaman               1200
0800140031040000 10-OCT-17 09.20.38 PM  10-OCT-17 09.21.30 PM  I                       1 lijiaman               1000

--第四步:根据闪回版本查询结果,执行闪回事物查询
SQL> select xid,start_timestamp,operation,table_name,undo_sql from flashback_transaction_query where xid = hextoraw('0800140031040000');                  --与上面事物1对应的版本查询
 
XID              START_TIMESTAMP OPERATION TABLE_NAME  UNDO_SQL
---------------- --------------- --------- ----------- ---------------------------------------------------------------
0800140031040000 2017/10/10 21:2 INSERT    TEST06      delete from "SYS"."TEST06" where ROWID = 'AAATteAABAAAU4ZAAA';
0800140031040000 2017/10/10 21:2 BEGIN                 
  
  
SQL> select xid,start_timestamp,operation,table_name,undo_sql from flashback_transaction_query where xid = hextoraw('05001C00F7040000');                --与上面事物2对应的版本查询
 
XID              START_TIMESTAMP OPERATION TABLE_NAME UNDO_SQL
---------------- --------------- --------- ---------- --------------------------------------------------------------------------------
05001C00F7040000 2017/10/10 21:2 UPDATE    TEST06     update "SYS"."TEST06" set "SALARY" = '1100' where ROWID = 'AAATteAABAAAU4ZAAA';
05001C00F7040000 2017/10/10 21:2 UPDATE    TEST06     update "SYS"."TEST06" set "SALARY" = '1000' where ROWID = 'AAATteAABAAAU4ZAAA';
05001C00F7040000 2017/10/10 21:2 BEGIN

 

(五)闪回表

(1)主要功能

闪回表是将表恢复到过去的某个状态,闪回表与闪回查询不同,闪回查询只是得到过去某个时刻的快照,并不改变表的当前状态,而闪回表则是将表及附属对象一起恢复到以前的某个时刻的状态。

(2)相关设置

(2.1)权限设置

为了使用FLASHBACK TABLE语句,用户需具有下列权限:

--需要具有FLASHBACK ANY TABLE系统权限,或者具有相应对象的FLASHBACK对象权限;

--用户对相应表需具有INSERT、SELECT、DELETE、ALTER的对象权限;

--如果要执行FLASHBACK TABLE … RESTORE POINT语句,需具有SELECT ANY DICTIONARY或FLASHBACK ANY TABLE系统权限,或具有SELECT_CATALOG_ROLE角色。

(2.2)表结构

当前表结构与要恢复到的时间点的表结构必需相同。例如表的升级(UPGRADE)、结构重组(MOVE)、数据的删减(TRUNCATE)、添加约束、修改列、删除列等操作都改变了表的结构,不能进行闪回操作。

(2.3)行移动

执行FLASHBACK TABLE之前,需要启用表的ROW MOVEMENT特性,闪回操作后,行的ROWID将会发生变化。

ALTER TABLE table_name ENABLE ROW MOVEMENT;

(3)语法

FLASHBACK TABLE [SCHEMA.]table_name TO SCN|TIMESTAMP expression
[ENABLE|DISABLE TRIGGERS]

参数解释:

--ENABLE|DISABLE TRIGGERS:在闪回表的过程中,表上的触发器是启用还是禁用。默认在闪回表的过程中禁用触发器,闪回完成后启用触发器

(4)例子4、闪回表操作

--创建测试样例

--17:08:12
create table test04
(
  id         number(2),
  name       varchar(20),
  salary     varchar(30)
);

--17:18:05
create index idx_test04_id on test04(id); 

--17:38:10
insert into test04 values(1,'liming',1000);

--17:39:08 
insert into test04 values(2,'zhanghua',2000);

--17:40:10
insert into test04 values(3,'wangfang',3000);

--17:41:11
update test04 set salary = 1100 where id = 1;

--17:42:06
delete from test04 where id = 3;

最终得到的表与索引如下:

SQL> select * from test04;
 ID NAME                 SALARY
--- -------------------- ------------------------------
  1 liming               1100
  2 zhanghua             2000


SQL> select index_name,table_name,status from user_indexes;
INDEX_NAME                     TABLE_NAME                     STATUS
------------------------------ ------------------------------ --------
IDX_TEST04_ID                  TEST04                         VALID

接下来,开启行移动:

--开启行移动
alter table test04 enable row movement;

执行闪回表操作:

--(1)将表闪回到17:42:00(在执行delete from test04 where id = 3之前)
flashback table test04 to timestamp to_timestamp('2017-10-09 17:42:00','yyyy-mm-dd hh24:mi:ss');

--查看结果:
--(1.1)表数据变化,发现被删除的数据被还原
17:48:18 SQL> select * from test04;

  ID NAME     SALARY
---------- -------------------- ------------------------------
   1 liming   1100
   2 zhanghua   2000
   3 wangfang   3000

--(1.2)索引未变化
SQL> select index_name,table_name,status from user_indexes;

INDEX_NAME               TABLE_NAME              STATUS
------------------------------ ----------------------------
IDX_TEST04_ID               TEST04                  VALID


--(2)将表闪回到17:41:00(在执行update test04 set salary = 1100 where id = 1之前)
17:49:12 SQL> flashback table test04 to timestamp to_timestamp('2017-10-09 17:41:00','yyyy-mm-dd hh24:mi:ss');

SQL> select * from test04;  --表中数据回到update之前的状态

  ID NAME     SALARY
---------- -------------------- ------------------------------
   1 liming   1000
   2 zhanghua   2000
   3 wangfang   3000

SQL> select index_name,table_name,status from user_indexes;
INDEX_NAME                     TABLE_NAME                     STATUS
------------------------------ ------------------------------ --------
IDX_TEST04_ID                  TEST04                         VALID

--(3)将表闪回到17:40:00(在执行insert into test04 values(3,'wangfang',3000)之前)
17:51:00 SQL> flashback table test04 to timestamp to_timestamp('2017-10-09 17:40:00','yyyy-mm-dd hh24:mi:ss');


17:52:37 SQL> select * from test04;    --只有2条数据

    ID NAME         SALARY
---------- -------------------- ------------------------------
     1 liming        1000
     2 zhanghua        2000

总结:

使用闪回表技术,可以将表闪回到过去的某个时刻。其附属对象(如,索引)也会返回到过去的某个状态,且不会失效。

(六)闪回删除

(1)主要功能

利用闪回删除可以恢复用DROP TABLE删除的表,是一种对意外删除的表的恢复机制。闪回删除主要是通过Oracle的回收站(recyclebin)功能实现的,在Oracle 11g中,当用户执行了DROP TABLE后,并不立即回收表极其相关联对象(索引、约束、触发器等)的空间,而是将它们重新命名后放入一个称为回收站的空间存储起来,当用户决定永久删除或该表的存储空间不足时,表才会被删除,空间才会被回收。

(2)回收站管理

(2.1)启用回收站

Oracle 11g默认开启回收站功能:

SQL> show parameter recyclebin
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
recyclebin                           string      on

如果未开启,则可以手动开启:

ALTER SYSTEM SET RECYCLEBIN=ON;

(2.2)查看回收站信息

可通过查看USER_RECYCLEBIN(synonym:RECYCLEBIN)、DBA_RECYCLEBIN来查看被删除表的信息

SQL> select object_name,original_name,type from dba_recyclebin;
 
OBJECT_NAME                    ORIGINAL_NAME                    TYPE
------------------------------ -------------------------------- -------------------------
BIN$Uo3E67rjHgvgUKjAhfUmRg==$0 MGMT_IP_REPORT_NLS_MAP           TABLE
BIN$Uo3E67riHgvgUKjAhfUmRg==$0 PK_MGMT_IP_NLS_MAP               INDEX

其中,OBJECT_NAME是删除对象在回收站中的名字,ORIGINAL_NAME是表的最初的名字。

(2.3)清除回收站

清除回收站的语法为:

PURGE [TABLE table_name] | [INDEX index_name] | [RECYCLEBIN] | [DBA_RECYCLEBIN] | [TABLESPACE tablespace_name [USER user_name]]

参数解释:

--TABLE:从回收站中清空表,并释放空间,表名可以使OBJECT_NAME,也可以是ORIGINAL_NAME;

--INDEX:与清空表一样;

--RECYCLEBIN:清空当前用户的回收站,并释放空间;

--DBA_RECYCLEBIN:清空数据库所有用户的回收站,并释放空间;

--TABLESPACE:清空回收站中指定表空间的对象,并释放空间;

--USER:清空回收站中指定表空间中指定用户的对象,并释放空间

(2.4)例子5、清空所有用户的回收站

SQL> purge dba_recyclebin ;

DBA Recyclebin purged.

(3)闪回删除操作语法

FLASHBACK TABLE [schema.]table_name TO BEFORE DROP [RENAME TO new_name];

(4)例子6、闪回删除测试

--测试表test05
SQL> select * from test05;    
 ID AGE NAME
--- --- --------------------
  1  20 lijiaman
  2  22 liudedong

--删除test05
SQL> drop table test05;
Table dropped

--查看表,已经不存在
SQL> select * from test05;
ORA-00942: table or view does not exis

--查看回收站,test05已经移动到了回收站
SQL> select object_name,original_name,type from user_recyclebin; 
OBJECT_NAME                    ORIGINAL_NAME                    TYPE
------------------------------ -------------------------------- -------------------------
BIN$Wx9kjXdn7QXgUKjAHwEcmQ==$0 TEST05                           TABLE

--执行闪回删除,将表还原
SQL> flashback table test05 to before drop; 
Done
 
--再次查看回收站,test05已经从回收站移出
SQL> select object_name,original_name,type from user_recyclebin; 
OBJECT_NAME                    ORIGINAL_NAME                    TYPE
------------------------------ -------------------------------- -------------------------

--再次查看test05表,已经还原回来
SQL> select * from test05; 
 ID AGE NAME
--- --- --------------------
  1  20 lijiaman
  2  22 liudedong

 

此外,闪回技术中还有闪回数据库和闪回数据归档未了解,由于在生产中并没有用到,不再详述。