oracle flashback query(闪回查询)

在Oracle 10g中,Flash back家族分为以下成员:
Flashback Database
Flashback Drop
Flashback Table
Flashback Query(分Flashback Query,Flashback Version Query,Flashback Transaction Query)
下面介绍一下Flashback Drop 和Flashback Table

Flashback DROP

Flashback Drop 是从Oracle 10g 开始出现的, 用于恢复用户误删除的对象(包括表,索引等), 这个技术依赖于Tablespace Recycle Bin(表空间回收站),这个功能和windows的回收站非常类似。
这个功能和数据库闪回没有关系,和flashback参数没有关系,表也不要求row movement.
经过测试SQL> alter database flashback off 能够闪回drop掉的表.
Flashback 不支持sys用户. system表空间下的对象,也不能从回收站里拿到。故使用SYS 或者SYSTEM用户登陆时,show recyclebin 为空。
1. Tablespace Recycle Bin
从Oracle 10g 开始, 每个表空间都会有一个叫作回收站的逻辑区域,当用户执行drop命令时, 被删除的表和表的关联对象( 包括索引, 约束,触发器,LOB段,LOB index 段) 不会被物理删除, 这些对象先转移到回收站中,这就给用户提供了一个恢复的可能。
初始化参数recyclebin 用于控制是否启用recyclebin功能,缺省是ON, 可以使用OFF关闭。
SQL> show parameter recycle
recyclebin string on

禁用该功能:
SQL> alter system set recyclebin=off;
SQL> alter system set recyclebin=on;
SQL> alter session set recyclebin=off;
SQL> alter session set recyclebin=on;
禁用后删除的对象将直接删除,不会写到Recycle中,当然在删除时,指定purge 参数,表也将直接删除,不会写到recyclebin中。

表空间的Recycle Bin 区域只是一个逻辑区域,而不是从表空间上物理的划出一块区域固定用于回收站,因此Recycle Bin是和普通对象共用表空间的存储区域,或者说是Recycle Bin的对象要和普通对象抢夺存储空间。当发生空间不够时,Oracle会按照先入先出的顺序覆盖Recycle Bin中的对象。也可以手动的删除Recycle Bin占用的空间。

1). Purge tablespace tablespace_name : 用于清空表空间的Recycle Bin
2). Purge tablespace tablespace_name user user_name: 清空指定表空间的Recycle Bin中指定用户的对象
3). Purge recyclebin: 删除当前用户的Recycle Bin中的对象
4). Purge dba_recyclebin: 删除所有用户的Recycle Bin中的对象,该命令要sysdba权限
5). Drop table table_name purge: 删除对象并且不放在Recycle Bin中,即永久的删除,不能用Flashback恢复。
6). Purge index recycle_bin_object_name: 当想释放Recycle bin的空间,又想能恢复表时,可以通过释放该对象的index所占用的空间来缓解空间压力。 因为索引是可以重建的。

2. Flashback Drop 实例操作

下面在系统参数recyclebin=on的时候操作:
1,SQL> drop table test1;
Table dropped.

2,查看recyclebin的信息
SQL> col origninal_name format a15;
SQL> col type format a15;
SQL> select object_name,original_name,type from user_recyclebin;

OBJECT_NAME ORIGINAL_NAME TYPE
------------------------------ -------------------------------- -------
BIN$fR5G/49+SZ2oESrTX4UCHg==$0 IDX_TESTID INDEX
BIN$x1Ey4hTFSeilywuQ7KKM+w==$0 TEST1 TABLE
SQL> show recyclebin; --注意这是sqlplus的命令
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST1 BIN$x1Ey4hTFSeilywuQ7KKM+w==$0 TABLE 2012-01-13:16:35:24

3,将删除的表闪回
SQL> flashback table test1 to before drop;
Flashback complete.
SQL> select * from test1;
ID NAME
---------- ----------
3763392 A

如果出现这样的情况,表test1删除后,一个同名的对象test1(表或者procedure..)被创建,闪回的时候需要重新命名
flashback table test1 to before drop rename to testX
还有一种情况是;同名的表被多次drop到了recyclebin中,这时候遵循后进先出的原则.
一旦完成闪回恢复,Recycle Bin中的对象就消失了.
SQL> select object_name,original_name,type from user_recyclebin;
no rows selected

在recyclebin被设置为off后不支持flashbacktable drop.
SQL> alter system set recyclebin=off;
System altered.
SQL> drop table test1;
Table dropped.
SQL> select object_name,original_name,type from user_recyclebin;
no rows selected

Flashback Drop 需要注意的地方:
1). 只能用于非系统表空间和本地管理的表空间
2). 对象的参考约束不会被恢复,指向该对象的外键约束需要重建。
3). 对象能否恢复成功,取决与对象空间是否被覆盖重用。
4). 当删除表时,信赖于该表的物化视图也会同时删除,但是由于物化视图并不会被放入recycle bin,因此当你执行flashback table to before drop 时,也不能恢复依赖其的物化视图,需要dba 手工介入重新创建。
5). 对于Recycle Bin中的对象,只支持查询.

Flashback Table

注意SYS用户不支持闪回,这点前面已经说明过。
Flashback Table也是使用UNDO tablespace的内容来实现对数据的回退。该命令相对简单,输入:flashback table table_name to scn(to timestamp) 即可。
注意:如果想要对表进行flashback,必须允许表的row movement.
Alter table table_name row movement;
要查看某表是否启用row movement,可以到user_tables 中查询(或all_tables,dba_tables),
例如:
SQL> select row_movement from user_tables where table_name='TEST1';
ROW_MOVE
--------
DISABLED
这时候为不支持行移动.

SQL> select current_scn from v$database;
CURRENT_SCN
-----------
3769840
SQL> delete from test1;
1 row deleted.
SQL> commit;
Commit complete.
SQL> flashback table test1 to scn 3769840;
flashback table test1 to scn 3769840
*
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled
这时候因为不支持行移动,出现上面的错误.
SQL> alter table test1 enable row movement;
Table altered.
SQL> flashback table test1 to scn 3769840;
Flashback complete.
SQL> select * from test1;
ID
----------
1
Flashback table 命令支持同时操作多个表,表名中间以逗号分隔即可,如果你执行一条flashback table命令时同时指定了多个表,要记住单个flashback table 是在同一个事务中,因此这些表的恢复操作要么都成功,要么都失败。
如:flashback table a,b ,c to scn 1103864;

基于undo 的表恢复,需要注意DDL 操作的影响
比如truncate table 后不能flashback table,会发生错误:ORA-01466:unable to read data -table definition has changed.
其他操作包括:drop/modify 列, move 表, drop 分区(如果有的话), truncate table/partition,这些操作会另undo 表空间中的撤销数据失效,对于执行过这些操作的表应用flashback query 会触发ORA-01466 错误。另外一些表结构修改语句虽然并不会影响到undo 表空间中的撤销记录,但有可能因表结构修改导致undo 中重做记录无法应用的情况,比如对于增加了约束,而flashback query 查询出的undo 记录已经不符合新建的约束条件,这个时候直接恢复显然不可能成功,你要么暂时disable 约束,要么通过适当逻辑,对要恢复的数据进行处理之后,再执行恢复。
另外,flashback query 对v$tables,x$tables 等动态性能视图无效,不过对于dba_*,all_*,user_*等数据字典是有效的。同时该特性也完全支持访问远端数据库,比如select * from tbl@dblink as of scn 360;的形式。
2. 基于undo 的表恢复,flashback table 实际上做的也是dml 操作(会在被操作的表上加dml 锁),因此还需要注意triggers 对其的影响,默认情况下,flashback table to scn/timestamp 在执行时会自动disable 掉与其操作表相差的triggers,如果你希望在此期间trigger 能够继续发挥做用,可以在flashback table 后附加
ENABLE TRIGGERS 子句。
Flashback Query
正如前言中所提,Flashback Query 是利用多版本读一致性的特性从UNDO 表空间读取操作前的记录数据!
什么是多版本读一致性
Oracle 采用了一种非常优秀的设计,通过undo 数据来确保写不堵塞读,简单的讲,不同的事务在写数据时,会将数据的前映像写入undo 表空间,这样如果同时有其它事务查询该表数据,则可以通过undo 表空间中数据的前映像来构造所需的完整记录集,而不需要等待写入的事务提交或回滚。

flashback query 有多种方式构建查询记录集,记录集的选择范围可以基于时间或基于scn,甚至可以同时查询出记录在undo 表空间中不同事务时的前映象。用法与标准查询非常类似,要通过flashback query 查询undo 中的撤销数据,最简单的方式只需要在标准查询语句的表名后面跟上as of timestamp(基于时间)或as of scn(基于scn)即可。as of timestamp|scn 的语法是自9iR2 后才开始提供支持。

这个功能和flashback on/off 以及recyclebin on/off没有关系.
1、As of timestamp 的示例:
SQL> select * from test1;
ID NAME
---------- ----------
3764577 1
SQL> select to_char(sysdate,'yy-mm-dd hh24:mi:ss') time from dual;
TIME
-----------------
12-01-13 16:59:29

模拟用户误操作,删除数据
SQL> alter table test1 enable row movement; --要将表改为可以允许行移动.
SQL> delete from test1;
SQL> commit;
SQL> select * from test1;
no rows selected

查看删除之前的状态:
假设当前距离删除数据已经有5 分钟左右的话:
SQL> select * from test1 as of timestamp sysdate-5/1440;
ID NAME
---------- ----------
3764577 1

或者:
SQL> select * from test1 as of timestamp to_timestamp('12-01-13 16:59:29','YY-MM-DD hh24:mi:ss');
ID NAME
---------- ----------
3764577 1
用Flashback Query恢复之前的数据:
SQL> insert into test1 select * from test1 as of timestamp to_timestamp('12-01-13 16:59:29','YY-MM-DD hh24:mi:ss');
1 row created.
SQL> commit;
SQL> select * from test1;
ID NAME
---------- ----------
3764577 1
如上述示例中所表示的,as of timestamp 的确非常易用,但是在某些情况下,我们建议使用as of scn 的方式执行flashback query,比如需要对多个相互有主外键约束的表进行恢复时,如果使用as of timestamp 的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过scn 方式则能够确保记录的约束一致性。

2. As of scn 示例
查看SCN:
SELECT dbms_flashback.get_system_change_number FROM dual;
SELECT CURRENT_SCN FROM V$DATABASE;
SQL> SELECT CURRENT_SCN FROM V$DATABASE;
CURRENT_SCN
-----------
3765554

删除数据:
SQL> delete from test1;
1 row deleted.
SQL> commit;
查看删除之前的状态:
SQL> select * from test1 as of scn 3765554;
ID NAME
---------- ----------
3764577 1
用Flashback Query恢复之前的数据:
SQL> insert into test1 select * from test1 as of scn 3765554;
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test1;
ID NAME
---------- ----------
3764577 1

事实上,Oracle 在内部都是使用scn,即使你指定的是as of timestamp,oracle 也会将其转换成scn,系统时间标记与scn 之间存在一张表,即SYS 下的SMON_SCN_TIME
每隔5 分钟,系统产生一次系统时间标记与scn 的匹配并存入sys.smon_scn_time 表,该表中记录了最近1440个系统时间标记与scn 的匹配记录,由于该表只维护了最近的1440 条记录,因此如果使用as of timestamp 的方式则只能flashback 最近5 天内的数据(假设系统是在持续不断运行并无中断或关机重启之类操作的话)。
注意理解系统时间标记与scn 的每5 分钟匹配一次这句话,举个例子,比如scn:3764577,3765348 分别匹配12-01-12 13:52:00 和12-01-12 13:57:00,则当你通过as of timestamp 查询12-01-12 13:52:00或12-01-12 13:57:00 这段时间点内的时间时,oracle 都会将其匹配为scn:3764577到undo 表空间中查找,也就说在这个时间内,不管你指定的时间点是什么,查询返回的都将是12-01-12 13:52:00 这个时刻的数据。
查看SCN 和timestamp 之间的对应关系:
select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')from sys.smon_scn_time;

Flashback version Query
相对于Flashback Query 只能看到某一点的对象状态,Oracle 10g引入的Flashback Version Query可以看到过去某个时间段内,记录是如何发生变化的。 根据这个历史,DBA就可以快速的判断数据是在什么时点发生了错误,进而恢复到之前的状态。
先看一个伪列ORA_ROWSCN. 所谓的伪列,就是假的,不存在的数据列,用户创建表时虽然没有指定,但是Oracle为了维护而添加的一些内部字段,这些字段可以像普通文件那样的使用。
最熟悉的伪列就是ROWID, 它相当于一个指针,指向记录在磁盘上的位置。ORA_ROWSCN 是Oracle 10g 新增的,暂且把它看作是记录最后一次被修改时的SCN。Flashback Version Query 就是通过这个伪列来跟踪出记录的变化历史。
举个例子:
SQL> select * from test1;
ID NAME
---------- ----------
3764577 1
SQL> insert into test1 values(dbms_flashback.get_system_change_number,'2');
1 row created.
SQL> select * from test1;
ID NAME
---------- ----------
3764577 1
3765736 2
SQL> commit;
SQL> select ora_rowscn,id,name from test1;
ORA_ROWSCN ID NAME
---------- ---------- ----------
3765611 3764577 1
3765611 3765736 2
获取更多的历史信息
SQL> Select versions_xid,versions_startscn,versions_endscn,
2 DECODE(versions_operation,'I','Insert','U','Update','D','Delete', 'Original') "Operation",
3 id,name from test1 versions between scn minvalue and maxvalue;
VERSIONS_XID VERSIONS_STARTSCN VERSIONS_ENDSCN Operatio ID NAME
---------------- ----------------- --------------- -------- ---------- ----------
0400210080030000 3765611 Insert 3764577 1
0400210080030000 3765611 Delete 3764577 1
03002A0049040000 3765520 3765611 Insert 3764577 1
03002A0049040000 3765520 Delete 3765348 A
3765520 Original 3765348 A
或者
SQL>select xid,commit_scn,commit_timestamp,operation,undo_sql
from flashback_transaction_query q where q.xid in(select versions_xid from B versions between scn 3764577 and 3765348 );
下面我们来讲下伪列,Flashback Version Query 技术其实有很多伪列,但是ORA_ROWSCN是最重要。它记录的是最后一次被修改时的SCN, 注意是被提交的修改。如果没有提交,这个伪列不会发生变化。
ORA_ROWSCN 缺省是数据块级别的,也就是一个数据块内的所有记录都是一个ORA_ROWSCN,数据块内任意一条记录被修改,这个数据库块内的所有记录的ORA_ROWSCN都会同时改变。上例的查询结果以证明。
不过我们可以在建表时使用关键字rowdependencies, 可以改变这种缺省行为,使用这个关键字后,每条记录都有自己的ORA_ROWSCN。
举例:
SQL> create table test1(id int,seq int) rowdependencies;
Table created.
SQL> insert into test1 values(dbms_flashback.get_system_change_number,1);
1 row created.
SQL> insert into test1 values(dbms_flashback.get_system_change_number,2);
1 row created.
SQL> commit;
Commit complete.
SQL> insert into test1 values(dbms_flashback.get_system_change_number,3);
1 row created.
SQL> commit;
Commit complete.
SQL> select ora_rowscn,id,seq from test1;
ORA_ROWSCN ID SEQ
---------- ---------- ----------
3769182 3769179 1
3769182 3769180 2
3769186 3769184 3

说明是最后一次被修改时的SCN,如果没有提交,是不会变的。

Flashback Transaction Query
Flashback Transaction Query也是使用UNDO信息来实现。利用这个功能可以查看某个事务执行的所有变化,它需要访问flashback_transaction_query 视图,这个视图的XID列代表事务ID,利用这个ID可以区分特定事务发生的所有数据变化。
示例:
SQL> truncate table test1;
Table truncated.
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
3769319
SQL> insert into test1 values(dbms_flashback.get_system_change_number,1);
1 row created.
SQL> commit;
Commit complete.
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
3769333

查看视图,每个事务都对应相同的XID
SQL> Select xid,operation,commit_scn,undo_sql from flashback_transaction_query where xid in (
2 Select versions_xid from test1 versions between scn minvalue and maxvalue);

XID OPERATION COMMIT_SCN
---------------- -------------------------------- ----------
UNDO_SQL
-----------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------
02000E009C040000 INSERT 3769330
delete from "YORKER"."TEST1" where ROWID = 'AAANlOAAEAAAAL2AAA';
02000E009C040000 BEGIN 3769330
或者
select xid,commit_scn,commit_timestamp,operation,undo_sql
from flashback_transaction_query q where q.xid in
(select versions_xid from test1 versions between scn 3769319 and 3769333);

你可能感兴趣的:(oracle)