oracle truncate table recover(oracle 如何拯救誤操作truncate的表)
生產上肯定是容易腦袋發熱,truncate一張表,立馬的心跳加速,眼神也不迷糊了,搞錯了,完了……
那麼,truncate表後,能不能進行恢復?
truncate操作是比較危險的操作,不記錄redo,也不能通過閃回查詢來找回資料,但是隻要段所佔用的塊沒有全部被重新佔用的情況下,我們還是可以通過一些特殊的辦法來找回truncate掉的資料,因為當Truncate命令發起之後,Oracle實際上並沒有在刪除底層資料塊上的資料,而是要等到重用的時候才會把這一部分資料回收,於是這給了我們一個能夠恢復資料庫的機會。
所以當truncate 表後,需要立馬的進行恢復,當尤其是生產上表空間不太夠的情況,或者是業務比較繁忙的情況,不一定能夠完全恢復truncate表的資料,所以時間就是金錢,理論上也不太可能把業務資料的表空間設定成read only狀態,所以,儘快進行恢復操作;
1.ORACLE官方上是dul能夠進行資料抽取
DUL 是Data Unloader 的縮寫,是一個荷蘭的Oracle 工程師開發的,他的名字為Bernard Van Duijnen。DUL 是一個C 開發的小程式,編譯後整個程式只有一個檔案,大小也不過幾百 KB,它工作時不需 Oracle RDBMS 以及任何的Oracle 的程式、元件,它可以直接從一個壞了資料庫的資料檔案中讀取資料,生成IMP 或SQL*Loader 可以識別的檔案。
DUL 不是一個商用化的產品,Oracle 不賣、不提供也不支援它的使用。DUL 只有在Oracle 的內部網站才可以下載到,因此也只有Oracle 的Supporter 才能下載到有這個工具。
2.FY_Recover_Data.zip 儲存過程恢復
如果我們已經有一套元資料及資料塊,然後將被TRUNCATE的使用者資料塊的內容取代其使用者資料塊的內容,是否可以“騙”過Oracle,讓它讀出這些資料呢?
回顧一下表掃描的過程,這個方法應該是可行的。我們只要想辦法構造出一個結構相同、且具有完整元資料資訊和格式化了的使用者資料塊的傀儡表物件,然後將被TRUNCATE的使用者資料塊找出,再將其資料內容部分嫁接到傀儡物件的使用者資料塊,使Oracle以外這是傀儡物件的資料,就能讓Oracle掃描並讀出資料內容。其原理用圖示描述如下:
下載地址:
http://www.hellodba.com/Download/FY_Recover_Data.zip
3.gDUL(這個後面再做測試)
-
完整支援多種格式匯出,包括expdp,exp,text格式。目前市面上的類dul工具只有gDUL支援expdp格式。
-
支援ASM檔案系統,並內建asmcmd命令。
-
支援絕大多數列型別,支援常見的NUMBER,CHAR, VARCHAR2, DATE,LOB, LONG等型別。
-
支援主流硬體平臺(HP-UX,AIX, Solaris, Linux, Windows),各個平臺僅需單一的可執行檔案,方便分發。
-
重點是——永久免費使用,無需額外費用,不開源。
gdul完全就是破解了dul,兩者想差不大,底層原理都一樣,下載地址:https://pan.baidu.com/s/1c1yrbkW#list/path=%2F
4.其他收費的資料抽取的工具就多了,比如odl,PRM-DUL,AUL/mydul
FY_Recover_Data.pck恢復truncate的表
可以參考案例:
http://www.hellodba.com/reader.php?ID=190&lang=CN
環境:oracle 19c
linux 7.6
恢復要求:FY_Recover_Data.pck支援windows和linux truncate表操作,
1.oracle有完整元資料資訊,系統表空間不能有問題。
2.執行的時候需要有dba許可權的使用者執行(最好是sys使用者,如果發現包狀態異常,那就是許可權過小,不能訪問一些檢視和系統表)
3.大寫(作者沒有整合大小寫,恢復的時候,輸入的物件名和使用者都是要大寫)
4.linux測試完恢復(tmp下有表空間的資料檔案,如果不用的話,建議刪除fy_rec_Data,fy_rst_data)表空間,不然伺服器重啟,資料庫起不起來(臨時檔案被清理了)
create table TEST_OBJ as select * from dba_objects;
insert into TEST_OBJ select * from dba_objects;
insert into TEST_OBJ select * from dba_objects;
insert into TEST_OBJ select * from TEST_OBJ ;
commit;
檢視這個包:
tow表示需要恢復的表的所有者(本次測試為SYS),ttb為表的名稱,fbks表示恢復表中要填寫的塊號(可選也可不填),後面臨時表空間,和離線檔案都預設為空;
truncate table TEST_OBJ ;
進行恢復。
我是用plsql develop
開啟FY_Recover_Data包,執行裡面的儲存過程recover_truncated_table;
plsql 命令列執行:exec fy_recover_data.recover_truncated_table('SYS','TEST_OBJ');
記住了,一定要是大寫,表名和使用者名稱.
14:01:05: Use existing Directory Name: FY_DATA_DIR
14:01:05: Recover Table: SYS.TEST_OBJ$
14:01:05: Restore Table: SYS.TEST_OBJ$$
14:01:09: Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT
14:01:09: begin to recover table SYS.TEST_OBJ
14:01:09: Use existing Directory Name: TMP_HF_DIR
14:01:09: Recovering data in datafile /u01/app/oracle/oradata/TEST19C/datafile/o1_mf_system_hnz0bpfm_.dbf
14:01:09: Use existing Directory Name: TMP_HF_DIR
14:04:07: 15550 truncated data blocks found.
14:04:07: 919872 records recovered in backup table SYS.TEST_OBJ$$
14:04:07: Total: 15550 truncated data blocks found.
14:04:07: Total: 919872 records recovered in backup table SYS.TEST_OBJ$$
14:04:07: Recovery completed.
14:04:07: Data has been recovered to SYS.TEST_OBJ$$
恢復出來了,如果被truncate表資料量很大,恢復時間比較久。
insert into TEST_OBJ select * from SYS.TEST_OBJ$$;
commit;
tmp下有表空間的資料檔案,如果用完了的話,建議刪除fy_rec_Data,fy_rst_data表空間。
drop tablespace fy_rec_data including contents and datafiles;
drop tablespace fy_rst_data including contents and datafiles;
下次需要恢復的時候建兩個表空間就好了。