Oracle Flashback 闪回—闪回查询


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的示例:

先创建一个很简单的表并插入一些记录用于测试:

SQL> 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

SQL> select * from t_fb_test;

 

      V_ID VA

---------- --

         1 a

         2 b

         3 c

         4 d

         5 e

         6 f

6 rows selected

 

删除几条记录并提交:

SQL> delete from t_fb_test where v_id < 4;

SQL> commit;

现在下面我们开始恢复查询:

SQL> 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 < 4;

 

3 rows inserted

 

SQL> 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 实现机制总结 》有详细介绍:

  • 1
  • 2
  • 下一页

相关内容