9i新特性之Flashback Query的應用-------------針對DML誤操作的恢復(2)

DBMS_FLASHBACK<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章