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 恢復誤操作的數據》