Flashback是Oracle自9i就開始提供的一項特性,在9i中利用oracle查詢多版本一致的特點,實現從復原段中讀取表一定時間內操作過的資料,可用來進行資料比對,或者修正意外提交造成的錯誤資料,該項特性也被稱為Flashback Query。在10g中Flashback又得到了相當大的增強,利用資源回收筒和閃回區的特性實現快速恢複刪除表(Flashback Table)或做資料庫時間點恢複(Flashback Database)的功能。
一、Flashback Query
Flashback Query是利用多版本讀一致性的特性從UNDO資料表空間讀取操作前的記錄資料!
什麼是多版本讀一致性
Oracle採用了一種非常優秀的設計,通過undo資料來確保寫不堵塞讀,簡單的講,不同的事務在寫資料時,會將資料的前映像寫入undo資料表空間,這樣如果同時有其它事務查詢該表資料,則可以通過undo資料表空間中資料的前映像來構造所需的完整記錄集,而不需要等待寫入的事務提交或復原。
flashback query有多種方式構建查詢記錄集(注意,要使用flashback的特性,必須啟用自動撤銷管理資料表空間) 記錄集的選擇範圍可以基於時間或基於scn,甚至可以同時查詢出記錄在undo資料表空間中不同事務時的前映象。用法與標準查詢非常類似,要通過flashback query查詢undo中的撤銷資料,最簡單的方式只需要在標準查詢語句的表名後面跟上as of timestamp(基於時間)或as of scn(基於scn)即可。
1、As of timestamp的樣本:
先建立一個很簡單的表並插入一些記錄用於測試:
SQL> create table t_fb_test(v_id,va) as 2 select 1,'a' from dual 3 union 4 select 2,'b' from dual 5 union 6 select 3,'c' from dual 7 union 8 select 4,'d' from dual 9 union 10 select 5,'e' from dual 11 union 12 select 6,'f' from dual; Table created SQL> select * from t_fb_test; V_ID VA ---------- -- 1 a 2 b 3 c 4 d 5 e 6 f 6 rows selected |
刪除幾條記錄並提交:
SQL> delete from t_fb_test where v_id < 4; SQL> commit; |
現在下面我們開始恢複查詢:
SQL> select * from t_fb_test as of timestamp sysdate-5/1440; V_ID VA ---------- -- 1 a 2 b 3 c 4 d 5 e 6 f 6 rows selected |
哈哈,資料又被我們找回來了(如果報錯:ORA-01466:無法讀取資料 – 表定義已經更改—這說明你間隔時間估計錯誤啦,操作過快5分鐘之前你還沒有建這表拉。)
我們通過增加as of timestamp的文法,就可以到undo資料表空間中尋找到5分鐘之前的記錄前鏡像,使用它我們就可以很輕易的並且迅速的將記錄恢複:
SQL> insert into t_fb_test 2 select * from t_fb_test as of timestamp sysdate-3/1440 where v_id < 4; 3 rows inserted SQL> commit; |
as of timestamp的確非常易用,但是在某些情況下,我們建議使用as of scn的方式執行flashback query,比如需要對多個相互有主外鍵約束的表進行恢複時,如果使用as of timestamp的方式,可能會由於時間點不統一的緣故造成資料選擇或插入失敗,通過scn方式則能夠確保記錄的約束一致性。
2、閃回查詢之As of scn:
我們通過dbms_flashback.get_system_change_number函數來擷取oracle當前的scn,之後再執行資料的修改操作。
SQL> select dbms_flashback.get_system_change_number from dual; GET_SYSTEM_CHANGE_NUMBER ------------------------ 14229608 |
刪除資料:
SQL> delete from t_fb_test where v_id > 4; 2 rows deleted SQL> commit; |
閃回查詢:
SQL> select * from t_fb_test as of scn 14229608; V_ID VA ---------- -- 1 a 2 b 3 c 4 d 5 e 6 f 6 rows selected |
然後我們可以用insert語句藉助 as of scn查詢結果將資料恢複回來。
事實上,Oracle在內部都是使用scn,即使你指定的是as of timestamp,oracle也會將其轉換成scn,系統時間標記與scn之間存在一張表,即SYS下的SMON_SCN_TIME
每隔5分鐘,系統產生一次系統時間標記與scn的匹配並存入sys.smon_scn_time表,該表中記錄了最近1440個系統時間標記與scn的匹配記錄,由於該表只維護了最近的1440條記錄,因此如果使用as of timestamp的方式則只能flashback最近5天內的資料(假設系統是在持續不斷運行並無中斷或關機重啟之類操作的話)。注意理解系統時間標記與scn的每5分鐘匹配一次這句話,舉個例子,比如scn:339988,339989分別匹配08-05-30 13:52:00和2008-13:57:00,則當你通過as of timestamp查詢08-05-30 13:52:00或08-05-30 13:56:59這段時間點內的時間時,oracle都會將其匹配為scn:339988到undo資料表空間中尋找,也就說在這個時間內,不管你指定的時間點是什麼,查詢返回的都將是08-05-30 13:52:00這個時刻的資料。
當然,具體的情況,我想你親自執行一下select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss') from sys.smon_scn_time,會理解的更深刻一些。
關於我SCN與timestamp/date時間之間的轉換,以及SCN實現機制原理可以看我另一篇博文《Oracle SCN 實現機制總結 》有詳細介紹: