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;

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

Oracle闪回技术

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

-- 查看表中目前数据,只有一行
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

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

上一篇:laravel强大功能路由初探(二)


下一篇:django rest_framework 序列化组件详解