生產上肯定是容易腦袋發熱,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 ;
進行恢復。
在執行的時候,查看登陸用戶有沒有權限:
select count(*) from sys.user$; select count(*) from sys.tab$; --如果查看不了這些視圖,說明用戶權限不夠,建議用sys,system或者具有dba權限用戶彩操作。
我是用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;
下次需要恢復的時候建兩個表空間就好了。
