Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2876024
  • 博文数量: 200
  • 博客积分: 2413
  • 博客等级: 大尉
  • 技术积分: 3067
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-01 22:07
文章分类

全部博文(200)

文章存档

2018年(2)

2017年(8)

2016年(35)

2015年(14)

2014年(20)

2013年(24)

2012年(53)

2011年(44)

分类: Oracle

2013-05-31 18:23:54

---###########################################
---利用黄炜(fuyuncat)的存储过程恢复被truncate表的数据
---##########################################

致谢:
首先,感谢这个恢复工具的作者黄炜(fuyuncat)。
没有他的帮助,也行我至今无法完成恢复测试。

在实验过程中,反复出现如下错误。
---
ORA-29283: 文件操作无效
ORA-06512: 在 "SYS.UTL_FILE", line 488
ORA-29283: 文件操作无效
ORA-06512: 在 "SYS.FY_RECOVER_DATA", line 765
ORA-06512: 在 "SYS.FY_RECOVER_DATA", line 820
ORA-06512: 在 line 21
---
走投无路,厚着脸皮给黄炜(fuyuncat)发了求助邮件。来回几封邮件后,问题迎刃而解。
黄大师指出,恢复时用到的目录必须和truncate表所在数据文件的目录一致。

再次感谢热情无私的黄大师!

在生产中,极有可能遇到不小心truncate表的情况,难道就这么等死吗?
不!黄炜(fuyuncat)给出了免费恢复数据的办法。




--原理
TRUNCATE不会逐个清除用户数据块上的数据,而仅仅重置数据字典和元数据块上的元数据(如存储段头和扩展段图)。
也就是说,此时,其基本数据并未被破坏,而是被系统回收、等待被重新分配————因此,要恢复被TRUNCATE的数据,
需要及时备份其所在的数据文件。

--参考:移花接木————利用Oracle表扫描机制恢复被Truncate的数据


--存储过程包
Fy_Recover_Data是利用Oracle表扫描机制、数据嫁接机制恢复TRUNCATE或者损坏数据的工具包。由纯PLSQL编写
wget

FY_Recover_Data.zip  (请不要下载,有问题!!!

FY_Recover_Data.sql   (正确版本

--##########
--实验模拟
--##########
1.创建一个表
create tablespace test datafile '/var/db_file/download/test01.dbf' size 10M autoextend on next 10M;
create user test identified by "test" default tablespace test;
grant connect,resource to test;

conn test/test
create table t1(id number,name varchar2(10));
insert into t1 values (1,'tom');
insert into t1 values (2,'lucy');
insert into t1 values (3,'tomd');
insert into t1 select * from t1;
SQL> commit;

Commit complete.


SQL> select count(*) from t1;

  COUNT(*)
----------
     49152

2.truncate表数据
SQL> truncate table test.T1;

3.恢复
--执行FY_Recover_Data.SQL 存储过程
$ unzip FY_Recover_Data.zip
Archive:  FY_Recover_Data.zip
  inflating: FY_Recover_Data.SQL     

--sys用户
SQL> @/home/oracle/FY_Recover_Data.SQL
Package created.
Package body created.


--找出test.t1表存放的目录,下一步有用
SQL> select file_name from dba_data_files f, dba_tables t where t.owner='TEST' and t.table_name='T1' and t.tablespace_name = f.tablespace_name;
FILE_NAME
--------------------------------------------------------------------------------
/var/db_file/download/test01.dbf

--开始恢复
SQL> 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 := 'TEST'; --table owner
     tgttable := 'T1';  --table name
     datapath := '/var/db_file/download/';    --必须和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;
   /
PL/SQL procedure successfully completed

注:执行上的SQL产生2个表空间(2个数据文件),还有1个copy文件。

---把恢复的数据从test.t1$$中插入test.t1表(test.t1$$中是test.t1表truncate之前的数据)
SQL> insert into test.t1 select * from test.t1$$;

49152 rows created.

SQL> commit;

Commit complete.

SQL> select count(*) from test.t1;

  COUNT(*)
----------
     49152

恢复后test.t1数据量和truncate之前相同,恢复成功了!

4.收尾
恢复数据后,把恢复时产生的2个表空间删除,再删除对应数据文件
drop tablespace FY_REC_DATA INCLUDING CONTENTS;
drop tablespace FY_RST_DATA INCLUDING CONTENTS;

$ cd /var/db_file/download/
$ rm FY_REC_DATA_COPY.DAT FY_REC_DATA.DAT FY_RST_DATA.DAT














阅读(13904) | 评论(7) | 转发(1) |
给主人留下些什么吧!~~

lijian19251172015-01-09 15:24:11

你好:能不能把FY_Recover_Data.zip 贴出来看看,我到hellodba网站上搜索,试了一下,报错不断。。

lw_9872013-06-30 15:42:25

学习了。