首页 > 开发 > 综合 > 正文

9i新特性之Flashback Query的应用-------------针对DML误操作的恢复(2

2024-07-21 02:08:46
字体:
来源:转载
供稿:网友

用dbms_flashback包

 

dbms_flashback 包提供了以下几个函数:

 

enable_at_time:设置当前session 的闪回查询时间

enable_at_system_change_number:设置当前session的闪回查询scn

get_system_change_number:取得当前数据库的scn

      disable:关闭当前session 的闪回查询

 

    如:

sql> select dbms_flashback.get_system_change_number from dual;

 

get_system_change_number

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

                 8053651

当将一个session 设置为闪回查询模式之后,后续的查询都会基于那个时间点或者scn 的数据库状态,如果session 结束,那么即使没有明确指定disable,闪回查询也会自动失效。在session 运行在闪回查询状态时,是不允许进行任何dml 和ddl 操作。如果要用dml操作来进行数据恢复就必须使用pl/sql 游标(其实,这里也就是给我们提供了一个数据恢复的方法)。即使session 运行在闪回查询模式,sysdate 函数也不会受到影响,仍然会返回当前正确的系统时间。

下面我们用一个例子说明如何使用dbms_flashback 包来恢复数据。

假设由于误操作删除了scott.emp 表中的所有数据,现在我们要恢复。

sql> delete from emp;

14 rows deleted.

sql> commit;

commit complete.

sql> select count(*) from emp;

count(*)

----------

0

然后执行下面的sql 创建一个存储过程用于恢复数据

create or replace procedure prc_recoveremp is

cursor c_emp is

select * from scott.emp;

v_row c_emp%rowtype;

begin

dbms_flashback.enable_at_time(systimestamp - interval '1' day);

open c_emp;

dbms_flashback.disable;

loop

fetch c_emp

into v_row;

exit when c_emp%notfound;

insert into scott.emp

values

(v_row.empno,

v_row.ename,

v_row.job,

v_row.mgr,

v_row.hiredate,

v_row.sal,

v_row.comm,

v_row.deptno);

end loop;

close c_emp;

commit;

end prc_recoveremp;

sql> execute prc_recoveremp;

pl/sql procedure successfully completed.

sql> select count(*) from emp;

count(*)

----------

14

到此成功结束,检查emp 表可以看到所有的数据已经全部都恢复了。

备注:在存储过程中我们创建了游标之后就将执行了dbms_flashback.disable,只

有这样我们才能在这个session 中进行dml 操作。否则将产生ora-08182 错误,in

flashback mode, user cannot perform dml or ddl operations。

上面我们已经介绍了关于如何的应用flashback query来恢复dml的误操作,但都是基于时间点(timestamp)的,其实呢,尽管timestamp可以精确到毫秒,可是由于{oracle 每隔5分钟会将产生的 scn 对应一个 time 做记录 ,也就是说通常只记录了scn,但是每5分钟会记录 scn and time  }(这段话需要深入的考究),当采用 timestamp 来做flashback 的时候就有可能产生偏差,5分钟的来由是在于表sys.smon_scn_time,我们可以察看一下:

该表的记录一共是1440行,那来几行可以看看

 

    thread    time_mp time_dp        scn_wrp    scn_bas

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

         1 1072772527 2003-12-30           0    8052536

         1 1072772834 2003-12-30           0    8053330

         1 1072773142 2003-12-30           0    8054053

         1 1072773446 2003-12-30           0    8054845

    可以看到,每行的timestamp差上5分钟左右,实际上,每5分钟,smon删除最旧的数据并且插入当前的信息,这也就可以推算出为什么无论你的undo retention 设置多大,flashback query 只能用5天(1440*5/24/60 )。所以基于scn的flashback query是最准确的

    举个例子看看:

sql> select * from lyb;

 

未选定行

sql> insert into lyb values (1);

 

已创建 1 行。

 

sql> commit;

 

提交完成。

 

sql> select dbms_flashback.get_system_change_number from dual;

 

get_system_change_number

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

                 8058302

 

sql> delete from lyb;

 

已删除 1 行。

 

sql> commit;

 

提交完成。

 

sql> select dbms_flashback.get_system_change_number from dual;

 

get_system_change_number

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

                 8058379

 

sql> select * from lyb as of scn 8058302

  2  ;

 

        id

----------

         1

sql> select * from lyb as of scn 8058379

2         ;

 

未选定行

sql>

 

 

所以说,基于scn的恢复才是能够做到精确!

当然,我们很明显遇到的问题是,如果真正的误操作,我那里会记录scn啊?这里就设计到另外的一个oracle很好用的工具,logminer,下次介绍!

 

注:sys 用户不允许执行dbms_flashback 包,将会产生ora-08185 错误,

flashback not supported for user sys

 

参考:

otn.oracle.com

asktom.oracle.com
seraphim(张乐奕)的《利用flashback query 恢复误操作的数据》


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表