Chanel [K]

面朝大海,春暖花开

How to recover data with DUL after table dropped

with 12 comments

首先系统情况如下:
1. Oracle版本是9.2.0.8,操作系统是IBM AIX
2. 数据文件存储在裸设备上
3. 被删除的表是分区表
4. 数据库非归档,没有任何备份
5. 在误drop table以后,立刻将包含该表的表空间offline了,并且保留了当时的current online redo文件
6. 保留了之前建表时的create脚本

恢复过程如下:
1. DUL使用的init.dul内容:

osd_big_endian_flag=true
osd_dba_file_bits=10
osd_c_struct_alignment=32
osd_file_leader_size=1
osd_word_size=32
 
control_file=/tmp/control.dul
db_block_size=8192
compatible=9

2. DUL使用的control.dul文件内容

58 58 /somepath/rawdevice1 4096 blocks 4095873
58 110 /somepath/rawdevice2 4096 blocks 639873
58 126 /somepath/rawdevice3 4096 blocks 255873

第1位是TS#,第2位是RFILE#,第3位是数据文件全路径,第4位是在AIX系统中裸设备需要跳过的字节,第5位是数据文件的真实block数(从v$datafile中以size/db_block_size获得)。

第4,5两位在数据文件为裸设备的情况下才需要,否则在scan database时扫描到裸设备结尾的时候,将可能报错。

3. 通过logminer得到被drop掉的表分区的data object id(因为被drop了,因此无法从system数据字典中获得)。如何使用Logminer不在本文范围内。
比如最后看到SQL_REDO字段的结果是类似于这样的输出:

DELETE FROM "SYS"."OBJ$" WHERE "OBJ#" = '25514' AND "DATAOBJ#" = '25514' ......

那么就可以知道data object id = 25514

4. 登录DUL

DUL> scan database;
DUL> unload table table_name partition(p_name) 
(col_name1 VARCHAR2(6),col_name2 VARCHAR2(17),col_name3 VARCHAR2(3).....) 
storage (dataobjno 25514);

这里的table_name和p_name其实都可以随便写,甚至不写partition也可以,最主要的是dataobjno必须正确,就可以unload出表数据。当然还必须有表结构,否则会报告无法在OBJ$中找到相应表。

如果此处没有事先保留的create table脚本,而且也不知道表中有哪些字段,那么工作量就大了。
基本步骤如下:

DUL> alter session set use_scanned_extent_map = true;
DUL> scan database;
DUL> scan tables;

然后在dul.log中查找上面的data object id,找到的话,将会是类似于下面的输出:

UNLOAD TABLE OBJNO25514 ( COL001 VARCHAR2(6), COL002 VARCHAR2(17), COL003 VARCHAR2(3)
        , COL004 VARCHAR2(26), COL005 VARCHAR2(30), COL006 NUMBER, COL007 NUMBER
        , COL008 VARCHAR2(1), COL009 NUMBER, COL010 VARCHAR2(38) )
    STORAGE( DATAOBJNO 25514 );

同时为了保险起见,在scan tables的过程中,DUL在log中还显示了该表的前5行记录内容,可以比对一下看看是否确实是被误删除的表。

之后,就是根据对于业务的了解,重新构建表结构了,其实对于只是删除了一张表而言,工作量还可以接受,但是如果是删除了整个USER …

5. 之后就是用sqlldr重新加载数据的事情了,不再赘述。

DUL格言是:Life without DUL

错误时刻都可能发生,为了数据的安全,为了自己工作饭碗的安全,还是做好备份吧。

Written by kamus

May 16th, 2009 at 11:41 am

Posted in Oracle RDBMS, Travel

Tagged with

12 Responses to 'How to recover data with DUL after table dropped'

Subscribe to comments with RSS or TrackBack to 'How to recover data with DUL after table dropped'.

  1. 刚用MyLOG+AUL恢复了一个这样的案例。

    anysql

    16 May 09 at 7:30 pm

  2. @anysql
    把MyLOG和AUL开源吧 >:) >:)

    kamus

    16 May 09 at 9:48 pm

  3. 被误删除的表是创建在ASSM的表空间上面吗?
    alter session set use_scanned_extent_map = true;的作用是什么?

    overmars

    18 May 09 at 5:12 pm

  4. 用 DUL和AUL 的过程都很痛苦

    boypoo

    18 May 09 at 10:55 pm

  5. kamus,你的头像怎么加进去的?

    boypoo

    18 May 09 at 10:56 pm

  6. @overmars
    在本例中不是ASSM
    作用是在没有数据字典的时候,告诉DUL用每个block自己头部的object id作为unload table的基础。

    Kamus

    19 May 09 at 9:08 am

  7. boypoo :
    用 DUL和AUL 的过程都很痛苦

    那尝试用一下老熊的ODU吧,呵呵

    Kamus

    19 May 09 at 9:13 am

  8. Kamus

    19 May 09 at 9:13 am

  9. 刚看了一下ODU, 命令语法和AUL差不多啊.

    anysql

    20 May 09 at 9:47 pm

  10. @anysql
    都是一样的unload数据方法,自然命令语法都差不多吧。
    我看了一下耿永辉的gDUL,语法也差不多。
    你们几个干脆一起做这个产品吧,何苦各自为营,劳动力浪费啊。

    Kamus

    21 May 09 at 10:33 am

  11. 除了直接访问ASM没搞定外,其他的都一个人搞定了,所以没想open source.

    anysql

    26 May 09 at 12:58 pm

  12. open source也不是为了解决自己一个人搞不定的技术难题。其实。。。open source是一种生活方式,呵呵。

    kamus

    26 May 09 at 2:07 pm

Leave a Reply