使用ODU恢复Truncate表

Posted by 老熊 on 3月 15th, 2009

意外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 »

TAF PartI

Posted by 老熊 on 3月 12th, 2009

TAF,透明应用故障转移(Transparent Application Failover),是Oracle数据库提供的一项高可用特性,普遍应用于RAC环境中,当然也可以用于Data Guard和传统的HA实现的主从热备的环境中。

TAF中的Transparent和Failover,点出了这个高可用特性的两大特点:

  • TAF是用于故障转移的,也就是切换。当Oracle连接的会话由于数据库发生故障不可用时,会话能够自动切换到RAC中的其他可用的节点上,或者切换到Standby上面,或者切换到HA方式中的另一个可用的节点上面。
  • TAF的故障转移,对应用来说是透明的,应用系统不需要进行特别的处理就能够自动进行故障转移。

但是,TAF是完美的吗?是不是使用了TAF,应用就能真的无缝地进行切换呢?对应用和数据库有没有其他什么要求?要回答这些问题,我们需要全面地了解、掌握TAF。我始终认为,要用好一个东西,首先得掌握这个东西背后的工作原理与机制。

首先来看看Failover。Failover有两种,一种是连接时Failover,另一种则是运行时Failover。前者的作用在于,应用(客户端)在连接数据库时,如果由于网络、实例故障等原因,连接不上时,能够连接数据库中的其他实例。后者的作用在于,对于一个已经在工作的会话(也就是连接已经建立),如果这个会话的实例异常中止等,应用(客户端)能够连接到数据库的其他实例(或备用库)。

首先,TAF是ORACLE客户端提供的一项特性。使用TAF,对客户端的环境有一定的要求。比如JAVA的JDBC驱动、Oracle客户端的版本等(8i开始支持TAF)。这个问题将在本系统文章的后面部分详细描述。

下面看一个有趣的例子:
Read the rest of this entry »

ODU命令详解 PartIII

Posted by 老熊 on 3月 3rd, 2009

接上文《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不能启动时(比如在关键的数据字典对象上有物理或逻辑坏块),用于分析块。dump命令的格式如下:

dump datafile <file#> block <block#>

这个命令格式与oracle的”alter system dump datafile“类似,这里的文件号是绝对文件号。
下面是几个示例输出:
Read the rest of this entry »

Oracle怎样标记坏块及一次数据恢复

Posted by 老熊 on 2月 24th, 2009

Oracle数据文件的坏块,可分为物理坏块和逻辑坏块。物理坏块(也可以称为介质坏块)指的是块格式本身是坏的,块内的数据没有任何意义。而逻辑坏块,指的是块内的数据在逻辑是存在问题。比如说索引块的索引值没有按从小到大排列。物理坏块一般是由于内存问题、OS问题、IO子系统问题和硬件引起,逻辑坏块一般是是由于Oracle Bug等原因引起。

Oracle数据文件的每个块,其块头为20字节。其定义如下:(来自于DSI401)

struct kcbh
{
    ub1 type_kcbh; /* block type */
    ub2 frmt_kcbh; 
    ub1 spare1_kcbh;
    ub1 spare2_kcbh;
    krdba rdba_kcbh; /* relative DBA */
    ub4 bas_kcbh; /* base of SCN */
    ub2 wrp_kcbh; /* wrap of SCN */
    ub1 seq_kcbh; /* sequence # of changes at the same scn */
    ub1 flg_kcbh; 
    ub2 chkval_kcbh;
};  
  

在块头中,seq_kcbh(占用1字节,块头偏移14)有着特殊的含义,如果该值为0xff,则表示该块被标记为corruption

下面我们做一个测试:

SQL> create table test.t1 as select * from dba_objects;

表已创建。

SQL> select header_file,header_block from dba_segments where segment_name=’T1′ and owner=’TEST’;

HEADER_FILE HEADER_BLOCK
----------- ------------
         10         1445

修改db_block_checksum参数值为TRUE,关闭数据库,我们用ultraedit修改10号文件的1447块的check sum(一个随便>0的数)及flag=0×04。然后再打开数据库。再执行下面的查询:

SQL> select count(*) from test.t1;
select count(*) from test.t1
*
ERROR 位于第 1 行:
ORA-01578: ORACLE 数据块损坏(文件号10,块号1447)
ORA-01110: 数据文件 10: ‘D:\ORACLE\ORADATA\XJ\TEST01.DBF’

由于非系统表空间在db_block_checksum参数设为FALSE时,会忽略checksum的检查。所以这里为了测试的方便设置为TRUE。
从上面的错误信息来看,块号1447这个块已经坏了,报的错误是经典的ORA-01578错误。
Read the rest of this entry »

ODU命令详解 PartII

Posted by 老熊 on 2月 19th, 2009

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

4.unload 命令

unload命令是ODU中命令格式最复杂的命令,但也是最关键的命令。命令的格式如下:

unload dict
unload table <schema.tablename> [partition <partition_name>]
unload table <schema.tablename> object <data_obj_id> [tablespace <ts_no>]
unload object <data_obj_id> [cluster <cluster_no>] [tablespace <ts_no>] column <type[,type,type......]>
    type: VARCHAR2 VARCHAR CHAR NUMBER SKIP LONG RAW                                                   
          DATE LONGRAW TIMESTAMP TIMESTAMPTZ TIMESTAMPLTZ                                              
          BINARY_FLOAT BINARY_DOUBLE  
unload user <schema name>

1) unload dict

unload dict用于从SYSTEM表空间解析数据字典,并将ODU所需要的数据字典数据保存到user.odu,tab.odu,obj.odu,col.odu,ind.odu等文件中。这样,ODU就可以利用数据字典信息UNLOAD数据。对于在有数据字典的情况下,ODU的功能能够得到最大程度地发挥:全面支持IOT表,全面支持LOB类型

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

值得注意的是,ODU并不是从文件号为1的数据文件中得到bootstrap地址进而得到数据字典,而是从control.txt的第一行中得到bootstrap地址。所以,需要将SYSTEM表空间中的第1个数据文件放置于control.txt中的第1行。否则会得到如下的错误:

can not get bootstrap$ address from SYSTEM tablespace

得到数据字典后,你可以使用list user, list table等命令查看数据库中的用户及用户下的表、视图等对象。

2) unload table <schema .tablename> [partition <partition_name>]

这个命令格式用于导出某个用户下的表,如果指定了partition,则只导出分区表中的那个分区。例如:

ODU> unload table sys.t1

Unloading table: T1,object ID: 31417
Unloading segment,storage(Obj#=31417 DataObj#=31418 TS#=0 File#=1 Block#=83041 Cluster=0)

导出表时,会显示表名,对象ID(Object ID),以及导出段的段头等信息。
使用此命令,表名要使用表的全限定名,则“用户名”+“表名“。

3) unload table <schema.tablename> object <data_obj_id> [tablespace <ts_no>]

此命令格式与上一命令格式的差别在于,在导出的表名之后指定了数据对象ID(data object id),这用于导出表其实际data object id与数据字典中表的data object id不一致时的表数据。简单点说,就是用于导出被truncate的表数据。导出前需要用SCAN命令扫描数据文件,导出truncate表的数据的详细操作,将另行撰文说明。

4) unload object <data_obj_id> [cluster <cluster_no>] [tablespace <ts_no>] column <type[,type,type......]>

这条命令简单点说,就是用于没有SYSTEM表空间或者没有数据字典时的数据导出,或用于导出被DROP了的表。

这条命令中,列类型为以下:

VARCHAR2 VARCHAR CHAR NUMBER SKIP LONG RAW
DATE LONGRAW TIMESTAMP TIMESTAMPTZ TIMESTAMPLTZ
BINARY_FLOAT BINARY_DOUBLE

SKIP表示不导出那个列。目前不支持没有数据字典(和SYSTEM表空间)时的IOT表和LOB类型的列。导出前需要用SCAN命令扫描数据文件。

此条命令和上条命令中,为啥可以指定TABLESPACE,这是因为在一个数据库中,data object id可能不是唯一的。比如,使用了表空间传输就可能会有这样的情况。

后面将专门有文章描述如何在没有数据字典时导出数据。这是一个比较复杂的过程,所以此处只是介绍一下命令,不再详述。

5) unload user <schema name>

此命令格式用于导出一个用户下的所有表。此命令在有数据字典时才支持。这样简化了导出一个用户下所有的表的操作。

贴一张儿子的照片

Posted by 老熊 on 2月 19th, 2009

贴一张儿子的PP上来

ODU命令详解 PartI

Posted by 老熊 on 2月 12th, 2009

本文将介绍ODU支持的命令,以v2.3.0为基础详细描述ODU的命令。

odu的命令以回车为结束,而不是像SQLPLUS那样的使用“;”号

1. help命令

help命令,显示ODU支持的命令列表,每个命令后面有简短描述:

ODU> help

help      ----   get command list
exit      ----   exit from odu
spool     ----   spool information to file
host      ----   enter os terminal
load config ----   load config information from file
open      ----   load database filename list from file
osdump    ----   dump file format hex
dump      ----   dump oracle datafile block
rowid     ----   decode rowid components
unload    ----   unload data
scan      ----   scan extent or segment
list      ----   list schema object,partition,datafile
charset   ----   get or list supported charset name

在执行一个命令时,如果输入的命令格式不对,将会提示那个命令的命令格式。

2. load config命令
load config命令用于载入ODU的配置文件。命令格式如下:

load config [filename]

缺省的文件名是config.txt
ODU在启动时,会自动载入名为config.txt的配置文件。我将撰文专门介绍ODU的配置文件。
ODU启动后,也可以重新载入配置文件,载入新配置后,会立即生效。

下面是一个示例:

ODU> load config
byte_order little
block_size 8192
db_timezone -7
client_timezone 8
data_path data
lob_path lob
charset_name ZHS16GBK
ncharset_name AL16UTF16
output_format text
lob_storage infile
clob_byte_order little
trace_level 4
delimiter |

load control file ‘config.txt’ successful

Read the rest of this entry »

ODU在Linux和Unix平台下的使用

Posted by 老熊 on 2月 9th, 2009

ODU网页下载到的ODU for Linux (Unix)版本,一般是以“odu_版本号_操作系统_平台.tar.gz”为文件名的文件。上传到你的机器后,使用gunzip和tar解压后,进行少许的配置即可使用。下面举例说明如何在Linux上的使用。

操作系统:Redhat Linux AS 5.0

将odu_210_linux_x86.tar.gz上传到oracle用户的home目录,这里为/export/home/oracle,输入命令:tar xzvf odu_210_linux_x86.tar.gz,即可解开压缩包。解开生成的所有文件和目录在/export/home/oracle/odu目录下。

如果这时候输入命令:./odu,则可能会报下面的错误:

./odu: error while loading shared libraries: libiconv.so.2: cannot open shared object file: No such file or directory

这是由于需要的库文件没有在搜索路径中。执行下面的命令:export LD_LIBRARY_PATH=/export/home/oracle/odu/lib:$LD_LIBRARY_PATH,再运行命令:./odu则会正常运行。

在Solaris平台下,这个环境变量也是LD_LIBRARY_PATH,但在AIX下,这个环境变量则是LIBPATH。

odu压缩包里面所包含的库文件或其不同的版本可能已经存在于系统中。为避免不同版本库文件引起问题,可在设置环境变量时将odu所在的lib目录放到环境变量中的前面部分。

为避免反复设置LD_LIBRARY_PATH和LIBPATH环境变量,可将此环境变量的设置,加入到用户的profile文件中。

UPDATE:
从3.0.7版本开始,各版本的不再需要设置环境变量,因为程序采用静态链接。

--EOF

ODU快速上手

Posted by 老熊 on 2月 8th, 2009

本文将以ODU 2.1.0 for Windows版,介绍如何使用ODU。本文只是一个快速上手指南,以后将详细介绍ODU的使用。

在本网站下载到ODU的Windows版本,是一个ZIP压缩文件,解压缩到一个目录,比如解压到d:\,将会看到d:\odu目录下有如下的文件和目录:

D:\odu>dir
驱动器 D 中的卷没有标签。
卷的序列号是 045E-00DE

D:\odu 的目录

2009-02-08  22:12    <DIR>          .
2009-02-08  22:12    <DIR>          ..
2009-02-08  01:16               218 config.txt
2009-02-08  01:16                99 control.txt
2009-02-08  22:12    <DIR>          data
2004-10-14  00:08           978,432 libiconv2.dll
2009-02-08  19:00           135,168 odu.exe
               4 个文件      1,113,917 字节
               3 个目录  1,738,174,464 可用字节

D:\odu>

如果没有data目录,请手工新建一个。

config.txt文件是ODU的配置文件,默认的配置数据如下:

byte_order little
block_size 8192
data_path data
lob_path lob
charset_name ZHS16GBK
ncharset_name AL16UTF16
output_format text
lob_storage file
clob_byte_order little
trace_level 1
file_header_offset 0
delimiter |

默认的配置基本能满足大部分的需求。

control.txt文件是ODU的数据文件信息文件。你可以理解为类似于Oracle数据库的控制文件,存放了ODU导出数据时需要的Oracle数据文件信息。

control.txt文件中的数据格式为:

表空间号 文件号 相对文件号 文件名 块大小 是否大文件表空间

每列之间用空白分隔,可以只需要前四列,即块大小和是否大文件表空间可省略,块大小省略时,数据文件的默认块大小为config.txt中block_size的大小。下面是一个示例的数据:

#ts #fno   #rfno     filename                                          block_size    bigfile
        0          1          1 D:\ORACLE\ORADATA\XJ\SYSTEM01.DBF              4096    
        1          2          2 D:\ORACLE\ORADATA\XJ\UNDOTBS01.DBF             4096
        3          3          3 D:\ORACLE\ORADATA\XJ\DRSYS01.DBF               4096
        4          4          4 D:\ORACLE\ORADATA\XJ\EXAMPLE01.DBF             4096
        5          5          5 D:\ORACLE\ORADATA\XJ\INDX01.DBF                4096
        6          6          6 D:\ORACLE\ORADATA\XJ\ODM01.DBF                 4096
        7          7          7 D:\ORACLE\ORADATA\XJ\TOOLS03.DBF               4096
        7          8          8 D:\ORACLE\ORADATA\XJ\TOOLS02.DBF               4096
        9          9          9 D:\ORACLE\ORADATA\XJ\XDB01.DBF                 4096
       11         10         10 D:\ORACLE\ORADATA\XJ\TEST01.DBF                2048
       14         11         11 D:\ORACLE\ORADATA\XJ\K16.DBF                  16384

如果数据文件头是完好的,则ODU会自动从文件头里面获取表空间号,文件号,相对文件号,文件块大小等。表空间号,文件号和相对文件号可以写为0。
注意:ODU将检查control.txt文件中的第一个数据文件是否为SYSTEM表空间文件,所以要将SYSTEM表空间的第1个文件放在control.txt文件中的第一行。否则将不能自动获得数据字典数据。
Read the rest of this entry »

发布ODU v2.0.1版

Posted by 老熊 on 2月 8th, 2009

ODU是一个类似Oracle DUL的软件。目前发布的是V2.0.1版。
访问本网站的ODU页面,可以得到更详细,最新的信息,也可以在那里下载到最新版本的ODU。

有任何问题可与我联系。详细的联系信息,参见本网站的关于页面。


Copyright © 2007 老熊的三分地-Oracle、UNIX、数据恢复. All rights reserved.