1. 程式人生 > >oracle資料庫中truncate表後如何快速恢復

oracle資料庫中truncate表後如何快速恢復

      在生產中,極有可能遇到不小心truncate表的情況,truncate表後不會產生日誌記錄和回滾段空間的使用,不能用閃回恢復。尤其是在沒有任何備份的情況下所以恢復起來相當麻煩,雖然在有備份的情況下是可以用rman恢復,但是在生產業務庫中,一般是不能輕易停庫的,而且為了一張表而關庫也會對其它正常的資料產生影響 ,所以這在時間上和空間上都是不可取的。那有沒有在不影響資料業務正常執行的情況下去快速恢復表呢,答案是確定的。

truncate原理:

       TRUNCATE不會逐個清除使用者資料塊上的資料,而僅僅重置資料字典和元資料塊上的元資料(如儲存段頭和擴充套件段圖)。也就是說,此時,其基本資料並未被破壞,而是被系統回收、等待被重新分配————因此,要恢復被TRUNCATE的資料,

需要及時備份其所在的資料檔案。

    方法:用儲存過程包Fy_Recover_Data     它是利用Oracle表掃描機制、資料嫁接機制恢復TRUNCATE或者損壞資料的工具包,這個包是由行內有影響力的DBA大師黃煒先生通過PLSQL編寫的,再這裡再次感謝他的無私技術分享。Fy_Recover_Data去本文附近中下載

好了,閒話少說,下面通過oracle資料庫中scott使用者自帶的emp表做測試:

步驟1:先把Fy_Recover_Data包拷貝到oracle相關目錄下

步驟2:在scott使用者下建立test_emp表:

SQL> conn scott/tiger;
Connected.
SQL> select * from tab;
TNAME      TABTYPECLUSTERID
------------------------------ ------- ----------
BONUS      TABLE
DEPT      TABLE
EMP               TABLE
SALGRADE      TABLE
SQL> select count(*) from emp;
  COUNT(*)
----------
14

SQL> create table test_emp  as select * from emp;
Table created.
SQL> select count(*) from test_emp;
  COUNT(*)
----------
14

步驟3:用truncate刪除test_emp表:

SQL> truncate table test_emp;
Table truncated.
SQL> select count(*) from 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 

步驟5:恢復

1)在sys使用者下執行儲存過程

SQL> @/home/oracle/FY_Recover_Data.SQL
Package created.
Package body created.

2)檢視test_emp表在資料檔案中的目錄

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


FILE_NAME
--------------------------------------------------------------------------------
/u03/oracle/oradata/WUTONG/datafile/o1_mf_users_cx3xt940_.dbf

3)通過指令碼恢復,可以用sqlplus命令列或者plsql developer執行

declare
      tgtowner varchar2(30);
      tgttable varchar2(30);
      datapath varchar2(4000);
      datadir varchar2(30);
      rects varchar2(30);
      recfile varchar2(30);
      rstts varchar2(30);
      rstfile varchar2(30);
     blksz number;
     rectab varchar2(30);
     rsttab varchar2(30);
     copyfile varchar2(30);
   begin
     tgtowner := 'SCOTT'; --table owner
     tgttable := 'TEST_EMP';  --table name
     datapath := '/u03/oracle/oradata/WUTONG/datafile/';    --必須和test.t1表所在的資料檔案的目錄相同
     datadir := 'FY_DATA_DIR';        --oracle中目錄的名字,可以修改
     Fy_Recover_data.prepare_files(tgtowner, tgttable, datapath, datadir, rects, recfile, rstts, rstfile, blksz);
     Fy_Recover_data.fill_blocks(tgtowner, tgttable, datadir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile);
     Fy_Recover_data.recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, datadir, datadir, recfile,datadir, copyfile, blksz);
   end;
   以上SQL指令碼產生2個表空間(2個數據檔案),還有1個copy檔案。

4)切換到scott使用者下檢視會發現多了些不一樣以test_emp的表,這時找到相關有資料的表,把資料插入原表test_emp

SQL> conn scott/tiger
Connected.
SQL> select * from tab;
TNAME      TABTYPECLUSTERID
------------------------------ ------- ----------
BONUS      TABLE
DEPT      TABLE
EMP      TABLE
SALGRADE      TABLE
TEST_EMP      TABLE
TEST_EMP$      TABLE
TEST_EMP$$      TABLE
7 rows selected.
SQL> insert into test_emp select * from TEST_EMP$$;
14 rows created.
SQL> commit;
Commit complete.
SQL> select count(*) from test_emp;
  COUNT(*)
----------
14

當你看到這一步的時候,說明truncate的表已經完全恢復了,恭喜你資料恢復成功!緊張的壓力隨之而釋放,臉上露出燦爛的笑容和自豪感(做DBA很辛苦,資料庫能保持正常執行,DBA在幕後做了大量的工作,有時是不會不被公司其他人理解的。。。。。)

步驟6:恢復資料後,把恢復時產生的2個表空間刪除,再刪除對應資料檔案

SQL> conn / as sysdba
Connected.
SQL> select name from v$datafile;
NAME
--------------------------------------------------------------------------------
/u03/oracle/oradata/WUTONG/datafile/o1_mf_system_cx3xt90z_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_sysaux_cx3xt930_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_undotbs1_cx3xt93b_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_users_cx3xt940_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_wutong_cx415lcj_.dbf
/u03/oracle/oradata/WUTONG/datafile/FY_REC_DATA.DAT
/u03/oracle/oradata/WUTONG/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/WUTONG/datafile/o1_mf_system_cx3xt90z_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_sysaux_cx3xt930_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_undotbs1_cx3xt93b_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_users_cx3xt940_.dbf
/u03/oracle/oradata/WUTONG/datafile/o1_mf_wutong_cx415lcj_.dbf

然後去作業系統下把對應的資料檔案刪除即可