加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

oracle_恢复Truncate表数据

(2013-01-08 15:09:46)
标签:

it

oracle

ddl

1.原理

首先,我们分析一下TRUNCATE的过程。TRUNCATE不会逐个清除用户数据块上的数据,而仅仅重置数据字典和元数据块上的元数据(如存储段头和扩 展段图)。也就是说,此时,其基本数据并未被破坏,而是被系统回收、等待被重新分配————因此,要恢复被TRUNCATE的数据,需要及时备份其所在的 数据文件。
然后,再分析一下表扫描的过程(我曾经在这篇文章中分析了小表扫描的过程:oracle逻辑IO的秘密: Full Table Scan: Part 1):Oracle 会读取段头的元数据,获得高水位线等信息,然后读取高水位线以下被格式化的数据块。因此,理论上讲,如果能够将被重置的元数据和元数据块重新构造出来,就 能使数据能被重新读取。然而,要完成这个任务,难度相当大————要找出原有的所有元数据块被保证其每个字节与被TRUANCATE之前完全相同———— 看起来似乎是一个不可能完成的任务。
不过,我们可以换一角度来找方法————如果我们已经有一套元数据及数据块,然后将被TRUNCATE的用户数据块的内容取代其用户数据块的内容,是否可以“骗”过Oracle,让它读出这些数据呢?
回顾一下表扫描的过程,这个方法应该是可行的。我们只要想办法构造出一个结构相同、且具有完整元数据信息和格式化了的用户数据块的傀儡表对象,然后将被 TRUNCATE的用户数据块找出,再将其数据内容部分嫁接到傀儡对象的用户数据块,使Oracle以外这是傀儡对象的数据,就能让Oracle扫描并读 出数据内容。其原理用图示描述如下:


http://s11/mw690/8317516bxd2c1aa74c08a&690


2.PL/SQL代码实现

    HELLODBA.COM>insert into demo.truntab select * from demo.t_objects; 
     
    47585 rows created. 
     
    HELLODBA.COM>commit; 
     
    Commit complete. 
     
    HELLODBA.COM>select count(*) from demo.truntab; 
     
      COUNT(*) 
    ---------- 
         47585 
     
    HELLODBA.COM>truncate table demo.truntab; 
     
    Table truncated. 
     
    HELLODBA.COM>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); 
     10    blksz number; 
     11    rectab varchar2(30); 
     12    rsttab varchar2(30); 
     13    copyfile varchar2(30); 
     14  begin 
     15    tgtowner := 'DEMO'; 
     16    tgttable := 'TRUNTAB'; 
     17    datapath := 'D:\oracle\product\10.2.0\oradata\EDGAR\DATAFILE\';
     18    datadir := 'FY_DATA_DIR'; 
     19    Fy_Recover_data.prepare_files(tgtowner, tgttable, datapath, datadir, rects, recfile, rstts, rstfile, blksz); 
     20    Fy_Recover_data.fill_blocks(tgtowner, tgttable, datadir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile); 
     21    Fy_Recover_data.recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, datadir, datadir, recfile,datadir, copyfile, blksz); 
     22  end; 
     23 
    Directory Name: FY_DATA_DIR 
    Recover Tablespace: FY_REC_DATA; Data File: FY_REC_DATA.DAT 
    Restore Tablespace: FY_RST_DATA; Data File: FY_RST_DATA.DAT 
    Recover Table: DEMO.TRUNTAB$ 
    Restore Table: DEMO.TRUNTAB$$ 
    Data Blocks formatted. 
    Copy file of Recover Tablespace: FY_REC_DATA_COPY.DAT 
    373 records recovered 
    328 records recovered 
    334 records recovered 
    .. ... 
    285 records recovered 
    275 records recovered 
    235 records recovered 
    47585 records recovered in backup table DEMO.TRUNTAB$$ 
     
    PL/SQL procedure successfully completed. 
     
    HELLODBA.COM>insert into demo.truntab select * from DEMO.TRUNTAB$$; 
     
    47585 rows created. 
     
    HELLODBA.COM>commit; 
     
    Commit complete. 

3.
我仅仅修改:
PLSQL包里面我仅仅修改:
datapath := '/u01/app/oracle11g/oradata/test/';

执行时我修改:
datapath := '/u01/app/oracle11g/oradata/test/';
datadir := 'DATA_PUMP_DIR';

最后说一下,恢复后建立2个表空间:
FY_REC_DATA
FY_RST_DATA

它的原理,大家自己看吧。


按照这个介绍:
http://www.hellodba.com/reader.php?ID=191&lang=CN
http://www.hellodba.com/reader.php?ID=191&lang=CN

包下载:
http://www.hellodba.com/download/FY_Recover_Data.zip

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有