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 恢复误操作的数据》