實際工作中,我們經常會遇到一些情況,誤刪除某些表或某些表的某些記錄,這時候就需要我們將這些記錄重新插入進去。如何才能解決這個問題呢?
Oracle的Flashback query(閃回查詢)為我們解決了這個問題 ,他的原理是Oracle根據undo信息,利用undo數據,類似一致性讀取方法,可以把表置於一個刪除前的時間點(或SCN),從而將數據找回。
下面我們先從簡單的例子來看閃回查詢的用法;
現有一張表有如下的數據
如果誤執行了delete語句,刪除其中一條記錄,或插入一個廢數據,修改了另外一個記錄,
delete hb where 姓名 = '張三';
insert into hb (姓名, 語文, 數學, 物理) values ('王五', 99, 99, 99);
update hb set 語文 = '60', 數學 = '60', 物理 = '60' where 姓名 = '李四';
這些操作,此時得到了如下的數據
我現在希望以上的操作全部回退,回到這最初始的狀態,此時就需要用到我們的Oracle提供的閃回查詢,
上面的閃回是基於時間點的,前面也說了還可以基於SCN來查詢,道理是一樣的,
通過查詢系統參數表,知道10點31分是28分的后面,所以我們查詢的所依據的SCN則采用14119586030431;
SELECT hb.*, sysdate FROM hb AS OF scn 14119586030431;
一樣可以得到上面的結果。這些都是查詢修改前的數據記錄,我們也可以直接將表整體閃回
flashback table hb to scn 14119586030431;
在此需要說明的是Oracle每5分鍾記錄一次SCN,並將SCN和對應時間的映射進行紀錄。如果原來插入的記錄到做閃回操作的時間在5分鍾之內,用基於時間的閃回查詢可能得不到記錄,因為基於時間點的查詢實際上是轉化為最近的一次SCN,然后從這個SCN開始進行恢復。因此,如果需要精確的查詢可以采用基於SCN的閃回查詢,可精確閃回到需要恢復的時間。可以通過
SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER FROM DUAL;
獲得系統當前的SCN。
(由於快照時間太久了,這上面我采用的新的SCN)這上面的是可以查看對應的時間段內對表所進行的操作:
versions_startscn,versions_starttime記錄了操作時的SCN或時間,如果為空,表示在查詢范圍外創建的
versions_endscn,versions_endtime記錄了失效時的SCN或時間,配合version_operation列查看,如果為空,或者被刪除、或者該記錄當前時間在當前表不存在
versions_operationI:insert D:delete U:update
versions_xid事務ID
以上這些都是表記錄級別的閃回查詢。知道了如何使用使用使用閃回查詢,那么原理呢?
我們知道,在Oracle中數據都是存儲在表空間中的,而閃回查詢就是查詢undo空間里的數據來實現的。
回滾段(undo)用於存放數據修改之前的位置和值,回滾段的頭部包含正在使用的該回滾段事務的信息。回滾段的作用如下:
(1)事務回滾:當事務修改表中數據的時候,該數據修改前的值(即前影像)會存放在回滾段中,當用戶回滾事務時,Oracle將會利用回滾段中的數據前影像來將修改的數據恢復到原來的值。
(2)事務恢復:當事務正在處理的時候,例程失敗,回滾段的信息保存在重做日志文件中,Oracle將在下次打開數據庫時利用回滾來恢復未提交的數據。
(3)讀一致性:當一個會話正在修改數據時,其它的會話將看不到該會話未提交的修改。而且,當一個語句正在執行時,該語句將看不到從該語句開始執行后的未提交的修改(語句級讀一致性)。這里就涉及到Oracle的事務級別,在此不做討論。
而Oracle的delete和commit操作的流程:
(1)delete流程 ,首先Oracle將數據塊讀到緩沖區中; 在“重做日志緩沖區”中記錄delete操作的全過程;在相應回滾段段頭的事務表中創建一個回滾條目;將要刪除的記錄創建前鏡像並存放到回滾段中;最后將相應的數據塊上刪除記錄並標記相應的數據塊為dirty。
(2)commit流程 ,Oracle產生一個SCN;在回滾段事務表中標記此事務為committed,然后日志讀寫進程將日志緩沖區中的記錄寫到日志文件。
所以后面我們通過閃回讀取的記錄都是回滾段中記錄的,換句話說,回滾段中有的數據我們可以通過閃回查詢查出來,沒有的數據的話就無法通過這個技術。
因此,要使用閃回查詢,undo_management必須設置為AUTO,undo_retention是undo保存數據的時間,單位是秒,設置的越大,就需要更大的表空間來支持,undo_tablespace即時回滾表空間的名稱。