非常规数据恢复的几种场景(利用ODU恢复被drop purge的表)

一、在表被drop purge后,为防止数据被覆盖,先offline表空间。
SQL> drop table test1 purge;
SQL> alter tablespace users offline;


二、找出被删除表的object_id
从redo log中找回被删除表的object id。表从回收箱里purge后,无法用flashback table test1 to before drop恢复,并且原
数据已从数据字典里删除。因此ODU无法读取表的原始数据(主要是object id),因此必须从redo log中查找相关资料。redo log中
的undo_sql会记录删除原数据的操作,从中可以找到对应的OBJECT ID.


首先找到当前的日志组
SQL> select member from v$logfile where group# = (select group# from v$log where status='CURRENT');
MEMBER
--------------------------------------------------------------------------------
/database/app/oracle/oradata/orcl/redo01.log


使用logmnr挖掘在线日志。想要找到被删除对象的object id,必须找到系统删除数据字典的语句。这里可以通过以下方法来查找:
先找到我们执行的drop table test1 purge 语句的执行时间,查这个时间点所有执行的SQL,然后自行判断一下。因为需要根据时间点来查,所以得把日期格式精确到秒,业务特别繁重的系统,可以把查找范围扩大到这个时间点前后几秒。
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss' ;
SQL> exec sys.dbms_logmnr.add_logfile(logfilename=>'/database/app/oracle/oradata/orcl/redo01.log');
SQL> exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);
查询logmnr的v$logmnr_contents视图
SQL> select scn,timestamp,sql_redo from v$logmnr_contents where operation='DDL' and sql_redo like '%test1%' order by 2 ;
scn     timestamp               sql_redo  
674364 2010-06-01 11:07:23 drop table test1 AS "BIN$h/BFvHxAzHfgQCAKRgEU5A==$0" ;
674397 2010-06-01 11:07:58 create table test1 (c int,d varchar2(20));
680444 2010-06-01 14:02:48 drop table test1 purge;


SQL> select scn,timestamp,sql_redo from v$logmnr_contents where timestamp=to_date('2010-06-01 14:02:48','yyyy-mm-dd hh24:mi:ss') order by 1;
"SCN"   "TIMESTAMP"             "SQL_REDO"
680449  2010-06-01 14:02:48     "delete from ""SYS"".""OBJ$"" where ""OBJ#"" = '52594' and ""DATAOBJ#"" = '52594' and ""OWNER#"" = '61' and ""NAME"" = 'TEST1' and ""NAMESPACE"" = '1' and ""SUBNAME"" IS NULL and ""TYPE#"" = '2' and ""CTIME""= TO_DATE('2010-06-01 11:07:58', 'yyyy-mm-dd hh24:mi:ss') and ""MTIME"" = TO_DATE('2010-06-01 11:07:58', 'yyyy-mm-dd hh24:mi:ss') and ""STIME"" = TO_DATE('2010-06-01 11:07:58', 'yyyy-mm-dd hh24:mi:ss') and ""STATUS"" = '1' and ""REMOTEOWNER"" IS NULL and ""LINKNAME"" IS NULL and ""FLAGS"" = '0' and ""OID$"" IS NULL and ""SPARE1"" = '6' and ""SPARE2"" = '1' and ""SPARE3"" IS NULL and ""SPARE4"" IS NULL and ""SPARE5"" IS NULL and ""SPARE6"" IS NULL and ROWID = 'AAAAASAABAAAMRrAA1';"
 
exec sys.dbms_logmnr.end_logmnr;
通过  ""OBJ#"" = '52594' and ""DATAOBJ#"" = '52594' 可以判断出test1的object id为52594


三、使用ODU恢复表
用odu直接扫描数据文件中的信息,然后读取指定对象ID的数据结构。
ODU> scan extent tablespace 4;
ODU> unload object 52594 sample
Unloading Object,object ID: 52594,  Cluster: 0
output data is in file :  'data/ODU_0000052594.txt'
Sample result:
  object id: 52594
  tablespace no: 4
  sampled 8 rows
  column count: 2
  column    1  type: NUMBER
  column    2  type: VARCHAR2
COMMAND: 
unload object 52594 tablespace 4 column NUMBER VARCHAR2
根据执行结果可以发现,ODU直接把object  52594的表结构、数据行数、列数以及列类型扫描出来了。
执行恢复
ODU> unload object 52594 tablespace 4 column NUMBER VARCHAR2
Unloading Object,object ID: 52594,  Cluster: 0
8 rows unloaded
确认一下导出的数据文件,发现不经过数字字典的恢复会多出一个文件sample.txt,就是ODU> unload object 52594 sample命令的结果。其他三个文件是系统根据object id自动命名的.继续查看三个用于恢复数据的文件,会发现执行恢复前有些东西需要手动改动下。
[oracle@dns1 data]$ ls
MWZ_TEST1.ctl  MWZ_TEST1.sql  ODU_0000052594.ctl  ODU_0000052594.txt
MWZ_TEST1.log  MWZ_TEST1.txt  ODU_0000052594.sql  sample.txt
[oracle@dns1 data]$ more ODU_0000052594.ctl
--
--Generated by ODU,for table ""."ODU_0000052594"
--
OPTIONS(BINDSIZE=8388608,READSIZE=8388608,ERRORS=-1,ROWS=50000)
LOAD DATA
INFILE 'ODU_0000052594.txt' "STR X'0a'"
APPEND INTO TABLE "ODU_0000052594"
FIELDS TERMINATED BY X'7c' TRAILING NULLCOLS
(
    "C0001" ,
    "C0002" CHAR(4000)
)
[oracle@dns1 data]$ more ODU_0000052594.sql
CREATE TABLE "ODU_0000052594"
(
    "C0001" NUMBER ,
    "C0002" VARCHAR2(4000) 
);
[oracle@dns1 data]$ more ODU_0000052594.txt
1|111
2|222
3|333
4|444
1|111
2|222
3|333
4|444
恢复前需要用ODU_0000052594.sql重建表,改文件需要手动修改表名和列名,把表名两边的""删除。sqlldr的控制文件同样需要修改表名和列名,以及列类型,把表名两边的""删除。其实把这三个文件的数据恢复到数据库中已经不再涉及到odu,因此可以根据自己的需要手动修改表结构。


四、恢复数据
登录SQLPLUS,先根据.sql文件重建表,然后通过sqlldr调用.ctl来恢复数据,具体操作和前面一样。留心检查一下恢复过程以及结果会发现,恢复出来的结果有8行,而我们原来测试的表中只有4行数据。这是因为前面为了恢复delete的数据,我们将配置文件中的unload_deleted  yes参数打开了,所以将第一次操作中被delete的数据都恢复了出来,下个实验我们将验证一下这个参数关闭后的效果。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值