Oracle Flashback Query(闪回查询技术)

Oracle 9i数据库就有闪回的功能,比如闪回查询,不过实现起来比较麻烦,需要使用dbms_flashback包来实现。从Oracle10g开始,Oracle对闪回概念做了极大的扩展,引入了很多新的闪回技术,比如flashback drop、flashback table、flashback database等等。闪回技术的引入,最主要的一个目的就是解决用户的逻辑错误,也就是用户在数据库里的误操作。当然了,对于闪回查询概念,Oracle也做了极大改进,实现起来更加的方便。

下面的实验就是一个闪回查询的小例子

SQL> conn scott/tiger
Connected.
SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
DEPT                           TABLE
EMP                            TABLE
BONUS                          TABLE
SALGRADE                       TABLE

创建表DEMO,作为测试表使用,在表里有6条的测试数据
SQL> create table demo as select empno,ename,sal
  2  from emp where rownum<=6;
Table created.

SQL> select * from demo;
     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             900
      7499 ALLEN            1600
      7521 WARD             1250
      7566 JONES            2975
      7654 MARTIN           2500
      7698 BLAKE            2850
6 rows selected.

在生产库,我们做操作的时候,显然不会总是查询当前的时间,不过这里为了做实验的简单,我们记录一下
SQL> select sysdate from dual;
SYSDATE
-------------------
2012-09-29 16:44:31


可以看到在 "16:44:31" 这个时间,表中是有6条数据的,接下来我们做delete操作,删掉表里的2条数据,并且提交,对于提交的操作,Oracle是无法通过

rollback把数据再恢复出来的。
SQL> delete demo where empno in (7369,7566);
2 rows deleted.

SQL> commit;
Commit complete.

如果做完操作后,用户意识到对表的修改有问题,比如上边的delete操作,这个时候可以选择使用闪回查询(flashback query)技术查询以前时间点的数据,也就是看在"2012-09-29 16:44:31"时间点上的数据,当然了,从当前时间点,到这个时间的时间间隔不要太长,因为Oracle的提交的数据是保留在UNDO表空间里的,提交的数据理论上会保留undo_retention参数指定的时间,但这个参数不是保证时间,是期望的时间。

有了闪回查询技术,我们既可以看当前时间点上的数据,也可以看以前的时间点上的数据,当然语法略有差异
SQL> select * from demo
  2  as of timestamp to_timestamp('2012-09-29 16:44:31','yyyy-mm-dd hh24:mi:ss');

     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             900
      7499 ALLEN            1600
      7521 WARD             1250
      7566 JONES            2975
      7654 MARTIN           2500
      7698 BLAKE            2850
6 rows selected.

SQL> select * from demo;

     EMPNO ENAME             SAL
---------- ---------- ----------
      7499 ALLEN            1600
      7521 WARD             1250
      7654 MARTIN           2500
      7698 BLAKE            2850

通过集合运算符minus,我们可以找到刚才delete操作处理的记录,当然再往下怎么操作,就取决于我们自己了
SQL> select * from demo
  2  as of timestamp to_timestamp('2012-09-29 16:44:31','yyyy-mm-dd hh24:mi:ss')
  3  minus
  4  select * from demo;

     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             900
      7566 JONES            2975


除了使用时间timestamp外,Oracle还可以使用SCN(系统改变号),其实数据库的内部时钟就是SCN。

scn和timestamp时间之间是可以做转换的,Oracle提供了两个函数,timestamp_to_scn和scn_to_timestamp,时间和scn的映射关系也保存在undo表空间里,Oracle 9i数据库这个映射的误差小于5分钟,Oracle10g以后,这个误差小于3秒。
SQL> select timestamp_to_scn(sysdate) from dual;

TIMESTAMP_TO_SCN(SYSDATE)
-------------------------
                  1938683

所以对于上边的闪回查询,我们也可以使用SCN的方式来做,当然首先要查到SCN
SQL> select timestamp_to_scn(to_timestamp('2012-09-29 16:44:31','yyyy-mm-dd hh24:mi:ss'))
  2  from dual;

TIMESTAMP_TO_SCN(TO_TIMESTAMP('2012-09-2916:44:31','YYYY-MM-DDHH24:MI:SS'))
---------------------------------------------------------------------------
                                                                    1938335

SQL> select * from demo as of scn 1938335;

     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             900
      7499 ALLEN            1600
      7521 WARD             1250
      7566 JONES            2975
      7654 MARTIN           2500
      7698 BLAKE            2850

6 rows selected.

原文地址:https://www.cnblogs.com/defended/p/3546338.html