oracle闪回查询


author:润明2012-2-3 QQ:226399587 https://blog.csdn.net/runming918
Flashback是ORACLE自9i就开始提供的一项特性,在9i中利用oracle查询多版本一致的特点,实现从回滚段中读取表一定内操作过的数据,可用来进行数据比对,或者修正意外提交造成的错误数据,该项特性也被称为Flashback Query。在10g中Flashback又得到了相当大的增强,利用回收站和闪回区的特性实现快速恢复删除表(Flashback Table)或做数据库点恢复(Flashback Database)的功能。

一、Flashback Query

Flashback Query是利用多版本读一致性的特性从UNDO表空间读取操作前的记录数据!
什么是多版本读一致性
Oracle采用了一种非常优秀的设计,通过undo数据来确保写不堵塞读,简单的讲,不同的事务在写数据时,会将数据的前映像写入undo表空间,这样如果同时有其它事务查询该表数据,则可以通过undo表空间中数据的前映像来构造所需的完整记录集,而不需要等待写入的事务提交或回滚。
flashback query有多种方式构建查询记录集(注意,要使用flashback的特性,必须启用自动撤销管理表空间) 记录集的选择范围可以基于或基于scn,甚至可以同时查询出记录在undo表空间中不同事务时的前映象。用法与标准查询非常类似,要通过flashback query查询undo中的撤销数据,最简单的方式只需要在标准查询语句的表名后面跟上as of timestamp(基于)或as of scn(基于scn)即可。

1、As of timestamp的示例:
先创建一个很简单的表并插入一些记录用于测试:
> create table t_fb_test(v_id,va) as
2 select 1,'a' from dual
3 union
4 select 2,'b' from dual
5 union
6 select 3,'c' from dual
7 union
8 select 4,'d' from dual
9 union
10 select 5,'e' from dual
11 union
12 select 6,'f' from dual;
Table created
> select * from t_fb_test;

V_ID VA
———- —
1 a
2 b
3 c
4 d
5 e
6 f
6 rows selected

删除几条记录并提交:
> delete from t_fb_test where v_id > commit;
现在下面我们开始恢复查询:
> select * from t_fb_test as of timestamp sysdate-5/1440;

V_ID VA
———- —
1 a
2 b
3 c
4 d
5 e
6 f

6 rows selected
哈哈,数据又被我们找回来了(如果报错:ORA-01466:无法读取数据 – 表定义已经更改—这说明你间隔估计错误啦,操作过快5分钟之前你还没有建这表拉。)
我们通过增加as of timestamp的语法,就可以到undo表空间中查找到5分钟之前的记录前镜像,使用它我们就可以很轻易的并且迅速的将记录恢复:
SQL> insert into t_fb_test
2 select * from t_fb_test as of timestamp sysdate-3/1440 where v_id commit;
as of timestamp的确非常易用,但是在某些情况下,我们建议使用as of scn的方式执行flashback query,比如需要对多个相互有主外键约束的表进行恢复时,如果使用as of timestamp的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过scn方式则能够确保记录的约束一致性。
2、闪回查询之As of scn:
我们通过dbms_flashback.get_system_change_number函数来获取oracle当前的scn,之后再执行数据的修改操作。
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
————————
14229608
删除数据:
SQL> delete from t_fb_test where v_id > 4;
2 rows deleted
SQL> commit;
闪回查询:
SQL> select * from t_fb_test as of scn 14229608;

V_ID VA
———- —
1 a
2 b
3 c
4 d
5 e
6 f
6 rows selected

然后我们可以用insert语句借助as of scn查询结果将数据恢复回来。
事实上,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:339988,339989分别匹配08-05-30 13:52:00和2008-13:57:00,则当你通过as of timestamp查询08-05-30 13:52:00或08-05-30 13:56:59这段时间点内的时间时,oracle都会将其匹配为scn:339988到undo表空间中查找,也就说在这个时间内,不管你指定的时间点是什么,查询返回的都将是08-05-30 13:52:00这个时刻的数据。
当然,具体的情况,我想你亲自执行一下select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss') from sys.smon_scn_time,会理解的更深刻一些。
关于我SCN与timestamp/date时间之间的转换,以及SCN实现机制原理可以看我另一篇博文《Oracle SCN 实现机制总结 》有详细介绍:https://www.2cto.com/database/201202/118597.html

3、Versions between版本查询

功能更加强大,通过versions between能够查看指定时间段内undo表空间中记录的不同版本(注意,只包括被提交的记录)。
版本查询的用法并不比as of复杂,与其类似,你只需要在标准查询后面附加versions between timestamp[/scn] t1 and t2即可。记录在版本查询中可能会是一对多的关系,比如某些记录如果被修改过多次,并分别提交,那么你在查询的时候,如果修改的操作是在你指定的时间段(或scn),则记录每次修改的结果都会被选择出来,这比较有利于我们做数据的对比,比如看看数据究竟是怎么变化的。

版本查询过程中提供了多个伪列如下:

VERSIONS_STARTSCN VERSIONS_STARTTIME
该记录操作时的scn或时间,如果为空,表示该行记录是在查询范围外创建的。

VERSIONS_ENDSCN

VERSIONS_ENDTIME
该记录失效时的scn或时间,如果为空,说明记录当前时间在当前表内存在,或者已经被删除了,可以配合着VERSIONS_OPERATION列来看,如果VERSIONS_OPERATION列值为D,说明该列已被删除,如果该列为空,则说明记录在这段时间无操作。

VERSIONS_OPERATION
对该行执行的操作:I表示insert,D表示delete,U表示update。

提示:对于索引键的update操作,版本查询可能会将其识别成两个操作:DELETE和INSERT。

VERSIONS_XID
该操作的事务ID

操作实例:(结果事例就不贴了)

SQL> select v_id,va,versions_startscn,versions_endscn,versions_operation from t_fb_test versions between scn 12372466 and 12372538 order by 1;

根据结果返回,每个记录各有两个版本,一行的VERSIONS_STARTSCN和VERSIONS_OPERATION有值,记录了开始时的SCN和执行的操作,另一行则是VERSIONS_ENDSCN有值,记录了该版本失效时的scn。

从VERSIONS_OPERATION列可以看出操作是:I表示insert,D表示delete,U表示update。

4、Transaction query事务查询

Flashback的事务查询是通过查询flashback_transaction_query视图来实现的。通过查询该视图能够获得一些事务执行时的信息,甚至包括UNDO语句。

select xid,commit_scn,commit_timestamp,operation,undo_sql

from flashback_transaction_query q where q.xid in( select versions_xid from t_fb_test versions between scn 23413946 and 23413959);

上述的查询结果已经清晰的向我们展示了我们所做的操作以及操作的时间等(实际执行的语句该视图并没有记录,只能通过undo_sql和operation推测),随着我们将事务范围的不断扩大,我们可以持续向前翻阅曾经做过的操作。当然,实际使用的时候需要注意,由于该视图存储记录量较大(究竟有多大呢,目前尚未找到相关文档有明确说明,初步预计,应该与smon_scn_time的存储规则有关系),查询的时候建议通过关键列过滤,比如logon_user啦,table_name或table_owner之类的,这么比起来这项操作倒确实与logminer非常想像,这简直就是个活的logminer啊,虽然只是一段时间内的。

5、制约因素
制约该特性应用的有三方面的因素

5.1 自动撤销管理表空间

这个是前面也提到了,要使用flashback的相关特性,必须启用自动撤销管理表空间,不仅是flashback query,也包括flashback table和flashback database,而对于后两项还会有些其它的附加条件,比如flashback table需要启用了recycle bin(回收站),flashback database还要求必须启用了flashback area(闪回区)。

5.2 初始化参数

初始化参数UNDO_RETENTION的设置严格说起来也是与undo表空间有关系,但是思量再三,我觉着还是有必要单拎出来详细介绍。
该参数用来指定undo记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改通常默认是900秒,也就是15分钟。
一定要注意,undo_retention只是指定undo数据的过期时间,并不是说,undo中的数据一定会在undo表空间中保存15分钟,比如说刚一个新事务开始的时候,如果undo表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建一个自动管理的undo表空间时,还要注意其空间大小,要尽可能保证undo表空间有足够的存储空间。
同时还要注意,也并不是说,undo_retention中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention参数的值并不会影响到你,哪怕你设置成1(这么说好像绝对了点,大家一定要注意理解,表钻牛角尖),只要没有事务去覆盖undo数据,它就会持续有效。因此呢,这里还是那句话,要注意undo表空间的大小,保证其有足够的存储空间。

5.3 DDL操作的影响

第三个就是修改并提交过数据之后,对表做过DDL操作,包括:
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;的形式。

声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 智乐兔
转载请注明:转自《oracle闪回查询
本文地址:https://www.zhiletu.com/archives-312.html
关注公众号:智乐兔

赞赏

wechat pay微信赞赏alipay pay支付宝赞赏

上一篇
下一篇

相关文章

在线留言

你必须 登录后 才能留言!

在线客服
在线客服 X

售前: 点击这里给我发消息
售后: 点击这里给我发消息

智乐兔官微