truncate表后的快速恢復方法(前提是沒有備份,沒有其他恢復手段時的特殊情況)


 

在數據庫運維中,相信大家都遇到過truncate表后,又需要找回數據的情況。但技術上因truncate表后不會產生日志記錄和未生成回滾段,因此不能使用常規在線方式恢復,當然也不能用閃回恢復。

 

常用的補救方法有:

1、有備份的情況下可以用rman恢復,但是在生產業務庫中,一般不能輕易停庫,而且為了一張表而關庫也會對其它正常的業務產生影響 ,所以這在時間上和空間上都是不可取的。

 

2、檢查誤刪除的表或分區是否有dmp備份,如有可以從dmp恢復;

 

那么無備份、無歸檔的情況下TRUNCATE掉的對象,是否還有更加迅捷的方法來恢復數據呢?筆者有位資深DBA朋友通過PLSQL編寫的一個存儲過程包Fy_Recover_Data,可以在不影響數據業務正常運行的情況下去快速恢復表。它是利用Oracle表掃描機制、數據嫁接機制恢復TRUNCATE或者損壞數據的工具包。

 

 

 

 

 

 

Fy_Recover_Data包的工作原理是:構造出一個結構相同、且具有完整元數據信息和格式化了的用戶數據塊的傀儡表對象,然后將被TRUNCATE的用戶數據塊找出,再將其數據內容部分嫁接到傀儡對象的用戶數據塊,使Oracle以為這是傀儡對象的數據,Oracle就可掃描並讀出數據內容。

 

其原理用圖示描述如下:

(Fy_Recover_Data包的工作原理)

 

以下是Fy_Recover_Data包的詳細使用操作過程:

 

(1) 先把Fy_Recover_Data包拷貝到數據庫主機相關目錄下(oracle用戶)

[oracle@dbaedu1 shsnc]$ ls -lrt

-rw-r--r-- 1 oracle oinstall 12888 Apr  7 00:42 FY_Recover_Data.zip

[oracle@dbaedu1 shsnc]$

 

(2) 在dbauser用戶下創建test_emp表

SYS@PROD> conn dbauser/#######

Connected.

DBAUSER@PROD> create table dbauser.test_emp as select * from dba_objects;

Table created.

DBAUSER@PROD> select count(*) from dbauser.test_emp;

COUNT(*)

----------

86975

 

(3) 用truncate刪除test_emp表

SQL> truncate table dbauser.test_emp;

Table truncated.

SQL> select count(*) from dbauser.test_emp;

COUNT(*)

----------

0

 

(4) 在linux中的oracle用戶下解壓FY_Recover_Data.zip包

$ unzip FY_Recover_Data.zip

Archive:  FY_Recover_Data.zip

inflating: FY_Recover_Data.SQL

[oracle@dbaedu1 shsnc]$ ls -lrt

-rw-r--r-- 1 oracle oinstall 79775 Apr  7 00:41 FY_Recover_Data.pck

[oracle@dbaedu1 shsnc]$

 

(5) 在sys用戶下執行存儲過程

SQL> @/home/oracle/shsnc/FY_Recover_Data.SQL

Package created.

Package body created.

 

(6) 查看test_emp表在數據文件中的目錄

select file_name from dba_data_files f, dba_tables t where t.owner='DBAUSER' and t.table_name='TEST_EMP' and t.tablespace_name = f.tablespace_name;

FILE_NAME

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

/u01/app/oracle/oradata/PROD/users01.dbf

 

(7) 通過腳本恢復,可以用sqlplus命令行或者plsqldeveloper執行

exec fy_recover_data.recover_truncated_table('DBAUSER','TEST_EMP');

 

(8) 切換到DBAUSER用戶下查看會發現多了些不一樣以test_emp的表,這時找到相關有數據的表,把數據插入原表test_emp

DBAUSER@PROD> select count(*) from dbauser.test_emp$$;

COUNT(*)

----------

86975

SQL> insert into test_emp select * from TEST_EMP$$;

86975 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from test_emp;

COUNT(*)

----------

86975

 

(9) 恢復數據后,把恢復時產生的2個表空間刪除,再刪除對應數據文件

SQL> conn / as sysdba

Connected.

SQL> select name from v$datafile;

NAME

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

/u03/oracle/oradata/datafile/o1_mf_system_xr5ht70z_.dbf

/u03/oracle/oradata/datafile/o1_mf_sysaux_xr5ht730_.dbf

/u03/oracle/oradata/datafile/o1_mf_undotbs1_xr5ht73b_.dbf

/u03/oracle/oradata/datafile/o1_mf_users_xr5ht740_.dbf

/u03/oracle/oradata/datafile/o1_mf_biboss_cx415lcj_.dbf

/u03/oracle/oradata/datafile/FY_REC_DATA.DAT

/u03/oracle/oradata/datafile/FY_RST_DATA.DAT

7 rows selected.

SQL>drop tablespace FY_REC_DATA INCLUDING CONTENTS;

Tablespace dropped.

SQL>drop tablespace FY_RST_DATA INCLUDING CONTENTS;

Tablespace dropped.

SQL> select name from v$datafile;

NAME

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

/u03/oracle/oradata/datafile/o1_mf_system_xr5ht70z_.dbf

/u03/oracle/oradata/datafile/o1_mf_sysaux_xr5ht730_.dbf

/u03/oracle/oradata/datafile/o1_mf_undotbs1_xr5ht73b_.dbf

/u03/oracle/oradata/datafile/o1_mf_users_xr5ht740_.dbf

/u03/oracle/oradata/datafile/o1_mf_biboss_cx415lcj_.dbf

 

(10)然后去操作系統下把對應的數據文件刪除即可。

 

對於使用工具fy_recover_data進行數據恢復,需要確保:

①truncate之后,需要保證沒有新的數據進入表中,否則無法還原;

②存放該表的數據文件塊不能被覆蓋,否則無法完整還原數據。

 

在發生故障后,可以迅速使用:

SQL> altertablespace users read only;

SQL> altertablespace users read write;

來關閉/開啟表空間的寫功能,這樣可以保證數據文件不會被覆寫。

 

當然,最后希望大家永遠不要用到今天分享的這個package。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM