由于ODU命令比较多,特别是关键的unload命令比较复杂,本文将简单介绍几种场景下使用ODU进行数据恢复时,使用的命令序列。本文不会详细介绍每个命令的使用,详细的命令请参考本网站ODU页面下的链接

场景1. 数据库不能启动,但是SYSTEM表空间中的数据字典是完整的。

  • 生成数据字典:unload dict
  • 列出用户: list user
  • 列出用户下的所有表: list table username
  • 恢复表: unload table username.tablename
  • 也可以按用户恢复: unload user username

场景2. 表被TRUNCATE。

  • OFFLINE表所在的表空间
  • 生成数据字典:unload dict
  • 显示表的段头:desc username.tablename
  • 找到实际的data object id: dump datafile file# block block#
  • 扫描数据:scan extent
  • 恢复表:unload table username.tablename object object_id

UPDATE:
从3.0.7版本开始,恢复Truncate表更方便,只需要执行下面的步骤:

  • OFFLINE表所在的表空间
  • 生成数据字典:unload dict
  • 扫描数据:scan extent
  • 恢复表:unload table username.tablename object auto

场景3. 表被DROP。

  • OFFLINE表所在的表空间
  • 使用logminer从日志里面挖掘被drop掉的表其data object id,如果不能挖掘,按下面的场景4进行恢复。
  • 扫描数据:scan extent
  • 如果没有表结构信息,需要自动来判断:unload object data_object_id sample
  • 恢复表:unload object data_object_id column coltype coltype...

场景4. 系统表空间损坏。

  • 扫描数据:scan extent
  • 搜索数据:unload object all sample
  • 从结果文件sample.txt查找需要的数据
  • 恢复需要的表:unload object data_object_id column coltype coltype...

场景5. 表中数据被DELETE。

  • 将参数unload_deleted设置为YES
  • 生成数据字典:unload dict
  • 恢复表: unload table username.tablename
,

本文将以ODU 3.0.2版的配置文件为例,详细介绍ODU的配置参数,从配置文件也可以体会到ODU的众多功能特点。

ODU默认的配置文件是config.txt,在启动ODU时,会自动打开这个配置文件,当然在进入ODU后,仍然可以通过"load config [config filename]"命令来装入配置文件,这个命令中的config filename(配置文件名)是可选的,如果省略此项,将载入默认的配置文件config.txt。

配置文件是一个纯文本文件,每行为一个配置参数,为“参数名”和“值”,二者均不区分大小写,之间以若干空格分隔。下面是一个配置文件的内容示例:

byte_order   little
block_size    8192
data_path   data
lob_path    /lob
charset_name ZHS16GBK
ncharset_name AL16UTF16
output_format text
lob_storage   infile
clob_byte_order  little
delimiter  |
unload_deleted no

下面将详细介绍每一项配置参数的用法以及作用:

1. BYTE_ORDER

这个参数,指示数据文件平台字节序。可选值为"LITTLE"和"BIG",默认值为“LITTLE”。

这个参数跟ODU运行在哪个平台无关,而只与数据文件的平台有关。比如,数据文件是AIX平台上的,那么这个值就是“BIG",而数据文件是x86平台上的,那么这个值就是”LITTLE“。ODU能够跨平台恢复数据,比如可以将AIX上的Oracle数据文件复制到Windows上,由Windows版本上的ODU进行恢复,反之亦然。只要通过BYTE_ORDER这个参数正确地指示数据文件的平台,即可实现跨平台恢复。

2. BLOCK_SIZE

这个参数设置数据文件缺省的块大小。ODU支持同一数据库具有不同块大小数据文件,如果在ODU的control文件中没有没文件指定块大小(参见《ODU命令详解 PartI》中“open”命令),则使用配置文件中的BLOCK_SIZE指定的大小。这个参数可选的值有2048、4096、8192、16384、32768,默认值是8192。

3. DATA_PATH

DATA_PATH指定恢复的数据所存储的目录,如果需要恢复的数量量非常大,可以用这个参数值指定一个与ODU软件所在目录不同的路径。注意这个参数指定的目录必须是已经存在的,ODU不会自动创建这个目录。
可以使用相对路径,也可以使用绝对路径。默认值为”data“,表示恢复的数据默认放在ODU软件所在目录的data子目录中。

4. LOB_PATH

Read the rest of this entry

,

虽然10g及以上版本的Oracle数据库,提供了recyclebin(回收站)功能,可以找回被drop的表。但是仍然存在着很多8i、9i的库以及没有开启recyclebin功能、drop时直接purge操作等,这样的情况下,如果想找回被意外drop的表,常规的手段是通过备份来恢复。如果没有备份,那就没有办法来恢复了。不过ODU提供了一个可能,在没有备份的情况下,恢复被drop表的数据。

下面通过一个示例来演示如何使用ODU来恢复被drop的表。
首先创建一个测试表:

SQL> create table odu_test ( a number,b varchar2(10),c nvarchar2(30),d varchar2(20),e date,f timestamp,g binary_float,h binary_double);

Table created.

SQL> insert into odu_test select rownum,lpad('x',10),'NC测试' || rownum, 'ZHS测试'|| rownum,sysdate+dbms_random.value(0,100),systimestamp+dbms_random.value(0,100),rownum+dbms_random.value(0,10000),rownum+dbms_random.value(0,10000) from dba_objects where rownum<=10000;

10000 rows created.

SQL> commit;

Commit complete.

SQL> create table t1 as select * from odu_test;

Table created.
SQL> drop table odu_test purge;

Table dropped.

在发现重要的表被意外drop掉的时候,应该立即停止应用,offline那个表所在的表空间或关闭数据库。这里odu_test表是建在users表空间下,先将users表空间offline:

SQL> alter tablespace users offline;

Tablespace altered.

然后需要使用logminer来查找被drop表的data object id:

SQL> select group#,status from v$log;

    GROUP# STATUS
---------- ----------------
         1 INACTIVE
         2 INACTIVE
         3 CURRENT

SQL> col member for a50
SQL> select member from v$logfile where group#=3;

MEMBER
--------------------------------------------------
/u01/app/oracle/oradata/xty/redo03.log

SQL> exec sys.dbms_logmnr.add_logfile(logfilename=>'/u01/app/oracle/oradata/xty/redo03.log');

PL/SQL procedure successfully completed.

SQL> exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);

PL/SQL procedure successfully completed.
SQL> select scn,timestamp,sql_redo from v$logmnr_contents where operation='DDL' and sql_redo like '%odu_test%' order by 2 ;

SCN TIMESTAMP SQL_REDO
---------- ------------------- ----------------------------------------------------------------------
    681455 2009-05-08 11:20:50 create table odu_test ( a number,b varchar2(10),c nvarchar2(30),d varc
                               har2(20),e date,f timestamp,g binary_float,h binary_double);

    681521 2009-05-08 11:21:17 create table t1 as select * from odu_test;
    681567 2009-05-08 11:21:34 drop table odu_test purge;

SQL> select scn,timestamp,sql_redo from v$logmnr_contents where timestamp=to_date('2009-05-08 11:21:34','yyyy-mm-dd hh24:mi:ss') order by 1;

       SCN  SQL_REDO
----------  ----------------------------------------------------------------------
    681566  set transaction read write;
    681567  drop table odu_test purge;
    681569  Unsupported
    681570  Unsupported
    681570 
    681570 
    681570 
    681570  Unsupported
    681570 
    681570 
    681570 
    681570  Unsupported
    681570 
    681570 
    681570 
    681570  Unsupported
    681570 
    681570 
    681570 
    681570 
    681570 
    681570 
    681570  Unsupported
    681570  Unsupported
    681570 
    681570 
    681570 
    681570  Unsupported
    681570 
    681570 
    681570 
    681570  Unsupported
    681570 
    681570 
    681570 
    681571  Unsupported
    681572 
    681572  delete from "SYS"."OBJ$" where "OBJ#" = '52230' and "DATAOBJ#" = '5223
            0' and "OWNER#" = '57' and "NAME" = 'ODU_TEST' and "NAMESPACE" = '1' a
            nd "SUBNAME" IS NULL and "TYPE#" = '2' and "CTIME" = TO_DATE('2009-05-
            08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "MTIME" = TO_DATE('2009-05-
            08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "STIME" = TO_DATE('2009-05-
            08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "STATUS" = '1' and "REMOTEO
            WNER" IS NULL and "LINKNAME" IS NULL and "FLAGS" = '0' and "OID$" IS N
            ULL and "SPARE1" = '6' and "SPARE2" = '1' and "SPARE3" IS NULL and "SP
            ARE4" IS NULL and "SPARE5" IS NULL and "SPARE6" IS NULL and ROWID = 'A
            AAAASAABAAAMzdAAS';

    681572 
    681573  commit;
    681574  set transaction read write;
    681574  Unsupported
    681576  commit;
    681577  set transaction read write;
    681579  Unsupported
    681581  commit;

SQL> exec sys.dbms_logmnr.end_logmnr;

PL/SQL procedure successfully completed.

从SCN为681572的几行中,delete from ”SYS”.”OBJ$” where ”OBJ#” = ’52230′ and ”DATAOBJ#” = ’52230′ 可以看到被drop表的data object id为52230。

下面我们使用ODU来恢复这个被删除的表:

Read the rest of this entry

,

意外Truncate表的事情时有发生,ODU提供了方便的恢复Truncate表的功能。被Truncate的表,只要原来的空间没有被重用(即数据被覆盖),则数据都是可以恢复的。

如果发现一个表被意外地Truncate,而需要马上恢复。首先要做的就是关闭数据库,或者OFFLINE那个表所在的表空间,或者关闭所有应用。目的只有一个,确保空间不会被重用,数据不会被覆盖。

下面举例说明如何用ODU恢复被Truncate掉的表。

1. 建立两个测试的表T1和T2,这两个表的数据完全一样。建两个数据完全一样的表的目的在于方便在恢复后对比数据。

SQL> connect test/test
已连接。

SQL> create table t1 as select * from dba_objects;

表已创建。

SQL> create table t2 as select * from t1;

表已创建。

SQL> truncate table t1;

表已截掉。

2. 我们OFFLINE掉T1表的表空间(实际上在实际的系统中,如果有比较多的活动,则表空间不容易被OFFLINE下来)。然后做一个Checkpoint,让ODU能够读到最新的数据字典数据。

SQL> select tablespace_name from user_tables where table_name='T1';

TABLESPACE_NAME
------------------------------
TEST

SQL> alter tablespace test offline;

表空间已更改。
SQL> alter system checkpoint;

系统已更改。

3. 运行ODU,并unload数据字典。

ODU> unload dict
get_bootstrap_dba: compat header size:12
CLUSTER C_USER# file_no: 1 block_no: 177
TABLE OBJ$ file_no: 1 block_no: 241
CLUSTER C_OBJ# file_no: 1 block_no: 49
CLUSTER C_OBJ# file_no: 1 block_no: 49
found IND$'s obj# 19
found IND$'s dataobj#:2,ts#:0,file#:1,block#:49,tab#:3
found TABPART$'s obj# 230
found TABPART$'s dataobj#:230,ts#:0,file#:1,block#:3313,tab#:0
found INDPART$'s obj# 234
found INDPART$'s dataobj#:234,ts#:0,file#:1,block#:3377,tab#:0
found TABSUBPART$'s obj# 240
found TABSUBPART$'s dataobj#:240,ts#:0,file#:1,block#:3473,tab#:0
found INDSUBPART$'s obj# 245
found INDSUBPART$'s dataobj#:245,ts#:0,file#:1,block#:3553,tab#:0
found IND$'s obj# 19
found IND$'s dataobj#:2,ts#:0,file#:1,block#:49,tab#:3
found LOB$'s obj# 156
found LOB$'s dataobj#:2,ts#:0,file#:1,block#:49,tab#:6
found LOBFRAG$'s obj# 258
found LOBFRAG$'s dataobj#:258,ts#:0,file#:1,block#:3761,tab#:0

Read the rest of this entry

,

接上文《ODU命令详解 PartII》,本文继续介绍ODU的命令

5.scan 命令

scan命令用于扫描数据文件中的segment以及extent。主要作用在于没有SYSTEM表空间时的数据恢复,以及TRUNCATE表和DROP表之后的数据恢复。命令格式如下:

scan extent [tablespace <ts#> [datafile <rfile#>] ] [object <data_object_id>]

扫描时可以指定表空间(只能指定表空间号),表空间中的1个文件;也可以扫描指定的data_object_id。扫描完成后,将在ODU的运行目录下生成ext.odu文件以及segment.txt文件,后者包含了扫描所找到的段头。

下面是一个示例:

ODU> scan extent tablespace 11

scanning extent...
scanning extent finished.

在恢复没有SYSTEM表空间和DROP,TRUNCATE表之前,需要运行scan命令。

6.dump 命令

dump命令模仿oracle的"alter system dump datafile"命令,解析并显示oracle的块格式。目前支持的块包括文件头(只有部分信息)、数据段头、表和索引数据块,其他的块只显示块头。这已经足够大部分情况的使用。ODU的升级版将解析并显示UNDO的段头和数据块。

dump命令用于帮助分析块格式,在ORACLE不能启动时(比如在关键的数据字典对象上有物理或逻