ORACLE FLAHBACK 系列(包含版本9與版本10)(zt)

tolywang發表於2007-07-30

第一章、前言

根據以往的經驗,很多操作失誤或者使用者錯誤,將導致應用停頓甚至終止,但是,實際上,防止這種誤操作的辦法是非常用限的。如果沒有良好的計劃與高超的技術,一個很小的錯誤將可能導致一個很大的影響,如錯誤的刪除(delete)資料或者是刪除(drop)一個表。

那怎麼樣來防止這種“不小心的操作呢”,Oracle從版本9開始,就開始提供了flashback query(閃回查詢)的功能,最初的功能也是很有限的,不僅完全依賴於自動Undo(AUM),對於droptruncateDDL操作是毫無辦法,而且,由於受到Undo空間限制,能閃回的時間也是有限的。Oracle的版本10中,對falshback做了巨大的改進,不再僅僅是侷限於AUM的閃回查詢了,甚至可以閃回整個資料庫,您將真正的回到操作之前的狀態。


在以下的章節中,我們將瞭解到如下的內容

1、 Oracle 9i開始的flashback query

2、 Oracle 9i開始的flashback exp

3、 Oracle 10gflashback database

4、 Oracle 10g flashback table

5、 Oracle 10g flashback drop

6、 Oracle 10g flashback version query

7、 Oracle 10g flashback transaction query

第二章、從Oracle 9i開始的flashback query

2.1Oracle 9iflashback query

在過去,如果使用者錯誤運算元據後,除了不完全恢復外,沒有好的解決辦法,到了Oracle9i,這一個難堪局面有所改善。Oracle 9i中提供了一項新的技術手段——flashback query(閃回查詢),這個功能的實現,由一個新的包DBMS_FLASH來實現。使用者使用閃回查詢可以及時取得誤操作前的資料,並可以針對錯誤進行相應的恢復措施。

如果需要用到閃回查詢,必須在init.ora或者是spfile.ora中設定以下引數UNDO_MANAGEMENT = AUTO ,在Oracle9i中,該引數預設就是AutoAUM)。與此相關的其它引數還有:

SQL> show parameter undo

NAME TYPE VALUE

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

undo_management string AUTO

undo_retention integer 10800

undo_suppress_errors boolean FALSE

undo_tablespace string UNDOTBS

除了確保以上引數中的UNDO_MANAGEMENT = AUTO外,還要注意另外一個引數undo_retention = n(秒),它決定了能往前閃回的最大時間,從引數也可以看到,這個引數決定了Undo最多的儲存時間,越大的值,就會需要更多的Undo空間的支援。我們可以透過如下的命令來修改該引數

SQL> ALTER SYSTEM SET undo_retention = 1200;

System altered.

以上的命令,告訴OracleUndo資訊將保持1200(20分鐘),這個將確保任何提交後的資訊在Undo中將保持20分鐘,除了可以一定程度的防止Ora-01555錯誤外,Falshback query將也直接的應用到其中的資訊。

現在,我們用一個簡單的例子來說明Oracle 9iflashback query

1、建立FLASH使用者

SQL> create user flash identified by flash;

SQL> grant connect, resource to flash;

SQL> grant execute on dbms_flashback to flash;

SQL> connect flash/flash

2、建立一個測試表

SQL> CREATE TABLE tst(t number(5));

Table created.

SQL> INSERT INTO tst VALUES(1);

1 row created.

SQL> INSERT INTO tst VALUES(2);

1 row created.

SQL> COMMIT;

Commit complete.

SQL> CREATE TABLE keep_date (date_scn_tracking date);

Table created.

SQL> SELECT * FROM tst;

T

----------

1

2

注意在執行步驟3或者步驟4之前,等待5分鐘。

3. 刪除記錄

SQL> execute dbms_flashback.disable;

PL/SQL procedure successfully completed.

SQL> INSERT INTO keep_date select sysdate from dual;

1 row created.

SQL> COMMIT;

Commit complete.

SQL> DELETE FROM tst WHERE t = 1;

1 row deleted.

SQL> COMMIT;

Commit complete.

SQL> SELECT * FROM tst;

T

----------

2

透過以上的操作,我們插入了兩條記錄,並刪除了其中一條記錄,現在的結果是,我們這裡只有一條記錄了。在以下的操作中,我們將透過flashback query找到刪除的記錄

4. 閃回查詢

SQL> declare

2 restore_scn date;

3 begin

4 select date_scn_tracking into restore_scn from keep_date;

5 dbms_flashback.enable_at_time(restore_scn);

6 end;

7 /

PL/SQL procedure successfully completed.

SQL> SELECT * FROM tst;

T

----------

1

2

可以看到,雖然我們刪除記錄並提交了,但是透過特定操作,我們還能查詢到刪除前的兩條記錄,

這裡需要特別注意的是,Oracle 9i是每五分鐘記錄一次SCN的,並將SCN和對應時間的對映做個紀錄。如果原來插入的記錄到做閃回的時間在5分鐘之內,用基於時間的flashback可能並查詢不到記錄,因為如果是基於時間點的查詢,也是轉化為最近的一次SCN,然後從這個SCN開始進行恢復,因此,如果需要精確的查詢,我們可以採用基於SCNflashback,它將能精確的閃回到需要恢復的時間,關於獲取SCN,我們可以透過DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER或者LOGMNR。如

DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(SCN_NUM);

來定位你的恢復時間點,下面是使用方法:

SQL> VARIABLE SCN_SAVE NUMBER;

SQL>EXECUTE :SCN_SAVE := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER;

PL/SQL procedure successfully completed.

SQL> print SCN_SAVE;

SCN_SAVE

----------

2.1202E+11

SQL>execute DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(:SCN_SAVE);

最後注意,Oracle 9iFlashback有如下限制。

·採用時間點的恢復,不能精確到最近5分鐘,如果需要更精確的查詢,需要採用SCN

·不能flashback5天以前的資料,這個並不是undo_retention所能決定的。

·閃回查詢無法恢復到表結構改變之前,因為閃回查詢使用的當前的資料字典。

·由於受到undo_retention的影響,對於undo_retention之前的時間,flashback不保證能成功

·對於drop,truncate等不記錄回滾的操作,flashback是無能為力的。

2.2Oracle 10gflashback query

Oracle 9iflashback query10g中也有了新的變化,10g中可以簡單的利用查詢語句實現flashback query,而不再需要象9i那樣需要呼叫DBMS_FLASHBACK包。

SELECT * FROM TABLENAME AS OF TIMESTAMP

TO_TIMESTAMP('2003-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')

WHERE ……;

或者

SELECT * FROM TABLENAME AS OF SCN

SCN_NUMBER

WHERE ……;

我們可以透過一個簡單例子來說明這個問題

SQL> create table t1 as select * from dba_objects;

Table created

SQL> select count(*) from t1;

COUNT(*)

----------

43116

可見,現在記錄是43116,我們獲得現在的系統SCN

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

377688

然後,我們刪除該表

SQL> delete from t1;

43116 rows deleted

SQL> commit;

Commit complete

透過如下檢查的查詢

SQL> SELECT count(*) FROM t1 AS OF SCN 377688;

COUNT(*)

----------

43116;

我們可以看到,查詢到的記錄數依然是刪除前的記錄數。

10g除了操作上的簡單外(不需要呼叫DBMS_FLASHBACK包),而且在基於時間上的flashback不再有5分鐘的限制了,也可以象SCN一樣進行精確的flashback query

第二章、從Oracle 9i開始的flashback exp

9i開始,exp工具開始提供閃回匯出,就是說,在現在時間,可以匯出上一個時間點的資料,exp工具將提供兩種閃回匯出的方法,以下是9i以後版本exp新增的兩個引數,預設情況下,它們都是”none”,如果被設定指定的值,將呼叫DBMS_FLASH包來獲取時間點上的資料

·基於SCN的匯出SCN (FLASHBACK_SCN)基於特定SCN的匯出

·基於時間的匯出time (FLASHBACK_TIME),基於特定的時間,但是影射為最近的SCN

1. 引數FLASHBACK_SCN

這個引數指定了一個exp匯出的特定的SCN,匯出的所有資料將保持這個SCN的一致性。預設情況下是none,表示不 呼叫flashback query,如

exp system/manager file=exp.dmp flashback_scn=2106860

2. 引數 FLASHBACK_TIME.

這個參數列示匯出將基於"YYYY-MM-DD HH24:MI:SS"的一個時間戳,exp將找到最近的一個SCN來代替這個時間戳來進行匯出。 預設是none,表示不呼叫flashback query,格式如

exp system/manager file=exp.dmp flashback_time='"2002-07-19 13:24:26"'

Oracle 9iflashback exp如同oracle 9iflashback query,它們有著同樣的侷限性(其實exp就是呼叫dbms_flash包),所以同樣需要設定AUMundo_retention,如果是時間方式,也不能精確到最近5分鐘。除此之外,因為exp呼叫了dbms_flash包,所以普通使用者如果想採用這種方式的匯出,必須授權,如

sqlplus /nolog

SQL> connect / as sysdba

SQL> GRANT execute ON dbms_flashback TO test;

SQL> exit

這兩個引數也不支援互動方式的匯出,只能用命令列方式或者是引數檔案。而且在表空間傳輸方式的時候,不能使用該方式。任何表結構的修改或者是Drop,truncateDDL語句也影響這種匯出方式,因為這些操作將引起undo無法正常會到以前的資料。

下面將舉例說明該問題

首先,我們設定相關環境變數

如果在win下面

C:> SET NLS_DATE_FORMAT=YYYY-MM-DD HH24:MI:SS

--如果是C SHELL

-- $ setenv NLS_DATE_FORMAT 'YYYY-MM-DD HH24:MI:SS'

-- KORN-shell:

-- $ export NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'

-- VMS:

-- DEFINE/NOLOG NLS_DATE_FORMAT "YYYY-MM-DD HH24:MI:SS"

SQL>conn / as sysdba

SQL>GRANT EXECUTE ON dbms_flashback to test;

-- 我們用SCOTT使用者登入並建立測試表

SQL>conn test/test

SQL>CREATE TABLE flash AS SELECT * FROM USER_OBJECTS;

SQL>SELECT COUNT(*) FROM flash;

COUNT(*)

----------

14;

SQL> SELECT SYSDATE, dbms_flashback.get_system_change_number FROM DUAL;

SYSDATE GET_SYSTEM_CHANGE_NUMBER

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

2004-4-13 13:15:21 386524

如果是版本9,為了防止ORA-1466 "table definition has changed"錯誤,需要等待5分鐘後操作,現在,假定等待了5分鐘,我們開始刪除表。

SQL> DELETE FROM flash;

SQL>COMMIT;

SQL>SELECT COUNT(*) FROM flash;

COUNT(*)

----------

0

可以看到,記錄已經被清除了,現在,我們執行匯出命令,可以看到,有14行從flash表中匯出

HOST exp test/test file=exp_flash.dmp log=exp_flash.log tables=flash

flashback_scn=386524

當然,10g也支援flashback exp,而且如同其它flashback的改進一樣,在10g中,你可以精確的利用時間點來匯出了。

第三章、ORACLE 10gFLAHSBACK新特性

Oracle 10gflashback有了強勁的改進,從普通的falshback query發展到了多種形式,主要表現在如下幾個主要方面。透過Oracle 10g,你甚至可以不需要從備份恢復,完成恢復工作。

l Oracle Flashback Database

這個特性允許你透過SQL語句FLASHBACK DATABSE語句,讓資料庫前滾到當前的前一個時間點或者SCN,而不需要做時間點的恢復。

l Oracle Flashback Table

這個特性允許你利用SQL語句FLASHBACK TABLE語句,確保回滾到表的前一個時間點。

l Oracle Flashback Drop

Oracle 10g開始提供一個類似垃圾站的功能,來恢復不小心被drop的表

l Oracle Flashback Version Query

利用儲存的回滾資訊,你可以看到特定的表在時間段內的任何修改,如電影的回放一樣,你將瞭解表在該期間的任何變化

l Oracle Flashback Transaction Query

這個特性將確保您檢查資料庫的任何改變在一個事務級別。你可以利用它來診斷問題,效能分析和審計事務

3.1Flashback database

閃回資料庫可以迅速的時資料庫回到誤操作或人為錯誤的前一個時間點,如實際中的“撤消”操作,將可以不利用備份就快速的實現時間點的恢復(有後悔藥可以吃了)。實際上,Oracle為了實現這一個功能,建立了另外一組日誌,就是Flashback Logs(前滾日誌),記錄資料庫的前滾操作。如果希望能閃回資料庫,需要設定如下引數:

·DB_RECOVER_FILE_DEST

·DB_RECOVER_FILE_DEST_SIZE

這兩個引數來確定Flashback日誌的存放地點與該恢復區的大小。在建立資料庫的時候,Oracle將自動建立恢復區(需要注意,該恢復區可不僅僅是為了flashback log,還可以用來歸檔,備份與恢復),但是預設是關閉Flashback database功能。如果想要利用這一功能,DBA就必須正確的配置該日誌區的大小,如一個資料庫的資料庫,每天有10%的塊發生改變,那麼一天(24小時)的Flash Recovery Area就是1/10個資料庫大小。DBA也可以動態的改變其大小以滿足不同的需求。

另外一個引數DB_FLASHBACK_RETENTION_TARGET引數允許您設定閃回資料的儲存時間,單位是分。預設是一天(24*60

如果想啟動FLASHBACK DATABASE的功能,您必須在MOUNT模式下,執行alter database flashback on命令。或者是alter tablespace tsname flashback on,資料庫將採集falshback log,如果需要關係該功能,則修改OnOFF

如果想執行flashback database命令,你可以在兩種方式下執行:RMANSQLPLUS,如

SQL >flashback database to time to_date(xxx);

SQL >flashback database to time TO_TIMESTAMP (xxx);

SQL >flashback database to scn xxx

SQL >flashback database to sequence xxx thread 1

SQL>flashback database to timestamp(sysdate-1/24)

我們下面看看具體的例子說明

SQL> startup mount

ORACLE instance started.

Total System Global Area 113246208 bytes

Fixed Size 787708 bytes

Variable Size 87030532 bytes

Database Buffers 25165824 bytes

Redo Buffers 262144 bytes

Database mounted.

SQL> alter database flashback on;

alter database flashback on

*

ERROR at line 1:

ORA-38706: Cannot turn on FLASHBACK DATABASE logging.

ORA-38707: Media recovery is not enabled.

可以看到flashback還必須要歸檔的保證

SQL> alter database archivelog;

Database altered.

SQL> alter database flashback on;

Database altered.

SQL> alter database open;

Database altered.

SQL> archive log list

Database log mode Archive Mode

Automatic archival Enabled

Archive destination USE_DB_RECOVERY_FILE_DEST

Oldest online log sequence 13

Next log sequence to archive 15

Current log sequence 15

經過以上步驟,我們確保了flashback database的功能,我們還可以發現,10g的自動歸檔是不需要手工干預的,只要開啟了歸檔,就是自動歸檔了,歸檔區也在DB_RECOVERY_FILE_DEST引數指定的地點。

透過如下的查詢

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SQL> SELECT OLDEST_FLASHBACK_SCN, OLDEST_FLASHBACK_TIME

2 FROM V$FLASHBACK_DATABASE_LOG;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI

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

1135440 2004-04-06 15:20:57

我們可以知道,可以前滾恢復到的最早的SCN與時間點是多少,如果沒有確保flashback database,該檢視將沒有查詢結果。

我們建立三個一樣的表

SQL> create table t1 as select * from dba_objects;

Table created.

SQL> create table t2 as select * from t1;

Table created.

SQL> create table t3 as select * from t1;

Table created.

SQL> set time on;

SQL> select sysdate from dual;

SYSDATE

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

2004-04-06 15:29:33

我們確定了一個時間點

現在,我們分別truncate一個表與drop一個表,模擬誤操作。

15:30:10 SQL> truncate table t2;

Table truncated.

15:30:43 SQL> drop table t3;

Table dropped.

沒有備份,我們利用flashback來恢復資料庫到2004-04-06 15:29:33時間點。

15:39:02 SQL> shutdown immediate;

Database closed.

Database dismounted.

ORACLE instance shut down.

15:39:31 SQL> startup mount exclusive

ORACLE instance started.

15:41:19 SQL> FLASHBACK DATABASE TO timestamp(to_date('2004-04-06 15:29:33','yyyy-mm-dd hh24:mi:ss'));

Flashback complete.

之後,我們可以用ALTER DATABASE OPEN READ ONLY來檢查結果是否正確如果滿足結果則可以用resetlog來正式啟動資料庫注意一旦resetlogs之後將不能再flashbackresetlogs之前的時間點。

15:41:32 SQL> alter database open resetlogs;

Database altered.

我們現在查詢那三個表

15:42:10 SQL> select count(*) from t1;

COUNT(*)

----------

47708

15:42:47 SQL> select count(*) from t2;

COUNT(*)

----------

47708

15:42:50 SQL> select count(*) from t3;

COUNT(*)

----------

47708

發現truncate的記錄或者是drop的表都存在,現在資料庫已經前滾到前一個時間點了。

15:44:56 SQL> SELECT OLDEST_FLASHBACK_SCN, OLDEST_FLASHBACK_TIME

15:45:05 2 FROM V$FLASHBACK_DATABASE_LOG;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI

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

1136169 2004-04-06 15:41:50

同時發現資料庫的最早的flashback的時間與scn都回到resetlog的時間點了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/35489/viewspace-84830/,如需轉載,請註明出處,否則將追究法律責任。

相關文章