Life is DUL without it
【IT168技术文档】
1 引言
经常有人在论坛上谈及DUL,问DUL的相关内容,要DUL。还有人不清楚DUL是什么东东,谁写的,做什么用的。一直想写一篇关于DUL稍完整些的文档,目的有两个,○1让不知道dul的人知道这是一个什么的东西,心里好有一个生存的底线,○2让用过dul的人有一个参考,放于身边,比英文的guide看起来更轻松、实用。
Life is DUL without it这句话是退出DUL工具时的一句提示,感觉非常有意思,找了英语精进的人也动用了在线的翻译也没准确表达出这句话的含义。我想,作者想表达的是DUL某些时侯同生命一样重要,就像一株救命的稻草,在特别的时侯会挽救生命。本文的着力点也不在于Oracle的Block结构如何如何,而在于这个工具如何的用,关于Block的内部结构可以参见DSI402及DSI402e。
本文所用的测试环境为:SUN 480机器+Solaris 9系统环境+Oracle 9.2.0.6数据库+DUL 9.2.4.4.2,部分章节使用了DUL 10.2.0.21B。目的只在于数据库知识的普及,特别需要提醒的是对于一个好的DBA,设计一个良好的、确实可行的备份策略并做好数据库备份特别重要,最好永远都用不到这样的工具。
2 关于DUL
2.1 DUL是一个什么样的程序
DUL是Data Unloader的缩写,是一个荷兰的Oracle工程师开发的,他的名字为Bernard Van Duijnen。DUL是一个C开发的小程序,编译后整个程序只有一个文件,大小也不过几百KB,它工作时不需Oracle RDBMS以及任何的Oracle的程序、组件,它可以直接从一个坏了数据库的数据文件中读取数据,生成IMP或SQL*Loader可以识别的文件。它观注的只是数据。存储过程、触发器、视图及建表语句这些脚本DUL是不生成的,不过如果系统表空间数据文件存在,可以通过数据字典表(sys.source$)折中的把这些脚本得到。
自Oracle 6.x这个数据库版本,For各种平台(Hp-unix,Aix,solaris,SCO Unix,Linux,windows…)的各个版本的Oracle都有Dul的相应版本。这个工具是Oracle不做技术支持的,也没有BUG的修订,它不是我们常规备份恢复操作的一个替代产品,而是在所有可能用到的手段都试过而不能解决问题时最后的一个数据挽救的方式。DUL可以用简单的一个命令卸载(unload)一个表,一个schema或整个库。DUL支持跨平台的Unload,比如可以将hp-unix平台的数据库的数据文件传到Aix平台做Unload操作。同时DUL的鲁棒性也非常的好,它不会因为数据库坏的不成样子hang住,或停在一点不动。总之,DUL是一个十分优秀的工具。
2.2 什么时侯用?
如果你的备份做的到位,可能你永远也用不到它。DUL是在一些特殊的情况下被用到的,例如在数据库没有有效的备份,系统表空间发生了损坏,而一些常规的手段(包括使用非文档参数(Undocument parameter),使用诊断事件,BBED或ORAPATCH工具修正)都无能为力无法解决问题时DUL才会被用到,它被称为last resort,即最后一种方法,也就是所有可能的方法你都试过了且不能解决问题时,才该用DUL。
2.3 哪里可以获得DUL
DUL不是一个商用化的产品,Oracle不卖、不提供也不支持它的使用。DUL只有在Oracle的内部网站才可以下载到,因此也只有Oracle的Supporter才能下载到有这个工具,如果与Oracle的Supporter熟悉,没准他私底下会给你一个,这个工具也因此有一些流落到民间,被一些人收入囊中,奉为珍宝。
不同的平台、不同版本的数据库都有相应的DUL软件,9.x及之前DUL是没有License限制的,也就是有这个工具可以无限制的使用,不过最新的DUL在这方面已经改进了,kamus说最新DUL拿到手只能用一个月。
关于这一小点稍总结一下,获得DUL有以下几种途径:
如果你是Oracle的Supporter,可以在内部网站下载,地址为:http://www.nl.oracle.com/support/dul/
如果你有Oracle的Supporter的朋友可以向他们要一个,itpub也几位斑竹都到Oracle了,如coolyl,kamus,lunar。
一些dul流落到民间,可以向有这软件的朋友要一个,不过他们不一定有你需要的那个。
2.4 使用前最好有哪些东西
数据库可能用尽各种方式启动不了,但要保证所有要挽救的数据所在的数据文件是完好的,且数据文件越新越好。数据文件的完好程度也决定了挽救回数据多少的完好程度,数据文件的坏块越来丢失的数据也越多。
最好有数据文件的列表。因为DUL工作的控制文件需要这些信息,光知道文件名是不够的,还需要数据文件所属的表空间的号(ts#),及数据文件号(rfile#),这些信息都位于v$datafile视图,因此在每次加数据文件后备份一下v$datafile视图相当必要。
应用所用到表等对象的数据字典或这些对象创建的DDL脚本。当系统表空间数据文件丢失时,DUL可以通过扫描发现表,但是无法明确哪张表叫什么名字,如果你对你的应用很了解也行,但大部分的时侯可能都不清楚扫描出来的对象对应的是哪张表,因此有对象的创建脚本是很有帮助的,存储过程、触发器、视图这些Object也可以很容易的重建回来。生成整个库的DDL脚本很容易,执行带FULL=y ROWS=n的EXP就可以了,也可以通过Dbartisan这样的工具去做。
你要对你的数据库、操作系统的有充足的了解;要有空间的准备,因为数据导出需要空间,备份原库或新库都需要空间;要有充足的耐心,特别是处理系统表空间数据文件丢失这样的情况,DBA这个工作的本身也要求这个人要胆大心细、有耐心及钻研精神。
Obj$或Dba_objects的备份,因为在无system表空间时,如果有这方面的备份会减轻很多工作。
2.5 DUL支持什么?
DUL支持分区表、索引组织表(IOT)这些选项,支持标准的数据类型及数据结构,具体如下:
支持行链接和行迁移
支持哈希和索引cluster
支持NULL列
支持LONG、RAW,DATE,NUMBER,ROWID
支持多free list group
支持多字节字符集
支持LOB类型列,不过需要注意的是,有LOB类型列的表在做DUL时输出需要为SQL*Loader格式。
2.6 DUL有什么限制和危险?
DUL毕竟是一个大小几百K的一个小工具而已,而Oracle功能越来越复杂,也因而有一些是DUL不支持或做的不完备的。前面已经提到,你的数据库可以是启动不了的,但是要Unload的数据的数据文件、数据块是保证是好的,因为DUL在Unload过程中会对数据块做检验,检验读到的数据块是不是块的,是不是属于正确的段。如果发现坏块,DUL会在屏幕显示出错误信息,同时将报错信息写到日志。
DUL不支持多级别安全标签(MLSLABEL),不支持VARRAY,object类型列,也不支持嵌套表。DUL在Unload过程中不会考虑到数据库一致性,它假定所有数据文件中的数据都是已经提交了的,没有了数据一致性的校验DUL实际做的是脏读,这是DUL比较大的缺点。不过关于这一点也是有点好处的,可以用此恢复truncate/drop误操作的表。
2.7 DUL的输出格式
以.dmp为输同格式时每表生成一个文件(owner_tablename.dmp),以sql*loader为输出格式时每表生成两个文件(owner_tablename.ctl和owner_tablename.dat)。如果设定了FILE参数,生成的文件名将会为FILEnnn.ext,如果你的操作系统不支持长文件名,FILE参数此时才会用到。
3 配置DUL
3.1 必需的配置文件
DUL正常运行需要两个配置文件,一个是init.dul,类似于数据库的init<SID>.ora文件,用于设定DUL运行中的各个参数及指定DUL的运行模式等内容。另外一个为control.dul,这个文件存放的是要Unload数据文件的相关信息。
3.2 参数据文件:init.dul
参数文件是dul运行必需的文件,下面会给出示例。参数文件用于设定DUL运行中的各个参数及指定DUL的运行模式等内容,例如缓存的大小、Oracle数据块的大小及输出文件格式等参数。Dul的运行参数分为四类,即数据库配置参数、数据字典缓存信息参数、操作系统相关参数及其它常用参数。
3.2.1 数据库配置参数
有如下两项:
Db_block_size:用于指定要做dul操作数据库的数据块的大小。
Compatible :与数据库的compatible参数相似,也是标识数据库的兼容版本的,只不过dul的compatible参数稍简单,不能指定小版本号,有效的值为6,7,8,9,10。Compatible这个参数是的取值也与你的dul版本有关,例如9.x版的dul是不支持Oracle10g的,因此compatible不能设置为10。
大部分dul参数都是有默认值的,不需设定,不过如上两个参数是必须设定的。
3.2.2 数据字典缓存参数
数据字典缓存参数是以dc_开头的四个参数,用于存放col$,tab$,obj$以及user$这几个数据字典表,相对应的参数为:
dc_columns
dc_tables
dc_objects
dc_users
这几个参数的类型都为number,且应该设的足够大能缓存下col$,tab$,ojb$,users$这几个数据字典表所有的行。其实,如果你设的小一点也没有关系,dul的鲁棒性特别的好,dc_xxxx这些参数会自动升为需要的值,在屏幕打出告警信息,然后继续工作,一点也不影响正常的操作。
告警信息示例:
DUL: Warning: Increased the size of DC_OBJECTS from 10000 to 20000 entries
即我的dc_columns设的是10000,而dul的启动过程中发现这个值是不够的,它自动给调也了20000。
3.2.3 操作系统相关参数
OSD_BIG_ENDIAN_FLAG
布尔类型。确定dul所工作的操作系统平台是不是byte-swapped的,通常HP,SUN平台machine word是big endian的,即osd_big_endian_flag=TRUE,DEC和Intel平台是little endian的,即osd_big_endian_flag=FALSE。如果你不确实这个值该为TRUE还是FALSE,可以通过如下的命令检测一下(UNIX平台):
$ echo dul |od –x
如果输出的结果为:
0000000 6475 6c0a
0000004
你运行的平台是big endian的,即osd_big_endian_flag=TRUE。
如果输出结果为:
0000000 7564 0a6c
0000004
你运行的平台是little endian的,即osd_big_endian_flag=FALSE。
OSD_DBA_FILE_BITS
数值类型。这个参数表示的是数据块地址中用于文件数低次序部分的位数。不太好理解,不过这不是问题的关键,知道如何设置,设置多大的值就可以了。
执行如下的语句,不同的返回结果这个参数该设成不同的值。
SQL>select dump(chartorowid(‘0.0.1’)) from dual; Typ=69 Len=6: 8,0,0,0,0,0 -> osd_dba_filebits = 5 (SCO) Typ=69 Len=6: 4,0,0,0,0,0 -> osd_dba_filebits = 6 (Sequent , HP) Typ=69 Len=6: 1,0,0,0,0,0 -> osd_dba_filebits = 8 (NCR,AIX) Typ=69 Len=6: 0,16,0,0,0,0 -> osd_dba_filebits = 12 (MVS) Typ=69 Len=10: 0,0,0,0,0,64,0,0,0,0 ->osd_dba_filebits = 10
OSD_C_STRUCT_ALIGNMENT
数值类型。这个参数表示的是数据文件头的结构布局,取值有三个0,16和32,大部分的平台这个值要设成32。可以通过如下的查询确定这个参数该设成哪个值。
SELECT * FROM V$TYPE_SIZE WHERE TYPE IN ('KCBH', 'KTNO', 'KCBH', 'KTBBH', 'KTBIT', 'KDBH', 'KTECT', 'KTETB', 'KTSHC'); 如果查询结果是如下这样的,osd_c_struct_alignment需设成32。 COMPONEN TYPE DESCRIPTION TYPE_SIZE -------- -------- -------------------------------- ---------- K KTNO TABLE NUMBER IN CLUSTER 1 KCB KCBH BLOCK COMMON HEADER 20 KTB KTBIT TRANSACTION VARIABLE HEADER 24 KTB KTBBH TRANSACTION FIXED HEADER 48 KDB KDBH DATA HEADER 14 KTE KTECT EXTENT CONTROL 44 KTE KTETB EXTENT TABLE 8 KTS KTSHC SEGMENT HEADER 8 8 rows selected.
对于VAX/VMS及Netware平台,结果通常如下,osd_c_struct_alignment需设成0。
COMPONEN TYPE DESCRIPTION TYPE_SIZE -------- -------- -------------------------------- ---------- K KTNO TABLE NUMBER IN CLUSTER 1 KCB KCBH BLOCK COMMON HEADER 20 KTB KTBIT TRANSACTION VARIABLE HEADER 24 KTB KTBBH TRANSACTION FIXED HEADER 48 KDB KDBH DATA HEADER 14 KTE KTECT EXTENT CONTROL 44 KTE KTETB EXTENT TABLE 8 KTS KTSHC SEGMENT HEADER 8 8 rows selected. OSD_FILE_LEADER_SIZE
数值类型。这个参数表示的是在Oracle数据文件中,真实的数据文件头块之前的块/字节的数量。对于AIX或DEC UNIX系统平台且使用裸设备做为数据文件时control.dul控制文件要加额外的字节偏移量,这在3.3.1中会提到。
osd_file_leader_size可以参照如下进行设置:
|
平台
|
值
|
|
Unix
|
1
|
|
Vms
|
0
|
|
Desktop
|
512
|
|
Others
|
未知
|
数值类型。表示的是machine word的大小,除一些特别的平台如MS-DOS这个值需设置为16外,其它的都为32。
3.2.4 其它常用参数
CONTROL_FILE
用于指定dul控制文件的名字,控制文件默认的名字为control.dul,如果你不想用这个名字,可以通过这个参数进行修改。
LDR_ENCLOSE_CHAR
当导出格式指定为sql*loader格式时,这个参数用于指定每个输出字段用什么括起来,与sql*loader控制文件中的ENCLOSED BY是相对应的。
举例:
//以双引号将输出字段括起来
LDR_ENCLOSE_CHAR = "
LDR_PHYS_REC_SIZE
当导出格式指定为sql*loader格式时,生成的sql*loader的dat文件每一行的大小,取值可以如下:
0 :每一行非固定长度,不论表的一条记录多长,sql*loader的dat文件每行存放一条记录。
>2:指定dat文件每行固定的长度,超过这个长度即换行。
BUFFER
表示的是dul输出缓冲区的大小,默认值为64KB,与性能有关,大一些值可以获得相对更好一些的性能。
举例:
//设定输出绥冲区大小为10MB
Buffer=10485760
EXPORT_MODE
布尔型的取值,这个参数决定dul的输出格式,默认值为FALSE。当其取值为FALSE时输出格式为sql*loader方式。当其取值为TRUE时,输出格式为exp/imp方式,即.dmp文件。
举例:
//以.dmp做为输出格式
Export_mode=TRUE
FILESIZE_IN_MB
这个参数用于指定输出文件最大的大小,在文件系统最大文件有限制的情况下使用,例如一些不支持大文件的文件系统最大文件大小为2GB。当输出文件超过这个参数设定的值时,输出文件为分隔成多个文件。其缺省值为0,表示的是输出文件不进行分隔。
举例:
//单个输出文件大小超2000MB分隔成多个文件
Filesize_in_mb=2000 3.2.5 参数文件举例 $ cat init.dul #my init.dul dc_columns = 200000 dc_tables = 10000 dc_objects = 10000 dc_users = 40 osd_big_endian_flag =true osd_dba_file_bits = 10 osd_c_struct_alignment = 32 osd_file_leader_size = 1 db_block_size = 8k LDR_ENCLOSE_CHAR = " LDR_PHYS_REC_SIZE = 81 compatible=9 EXPORT_MODE=TRUE BUFFER=10485760
3.3 控制文件:control.dul
3.3.1 控制文件格式说明
控制文件也是dul运行必需的文件,默认的名字为control.dul,包含了要做unload的数据文件的相关信息,dul通过它,把数据文件号对应到相应的数据文件。
Control.dul的格式为:
Ts# Relative_file# Data_file_name [extra leader offset ] [startblock#] [endblock#]
TS#,Relative_file#,Data_file_name:这三项源于v$datafile,是必需项目,分别对应v$datafile这个视图中的ts#,rfile#,代表每一个数据文件的表空间号,数据文件号。
extra leader offset:这一项是可选项目。一些系统环境,如AIX平台,数据文件头包含一些额外的块,这在dul做lseek操作时是需要跳过的,否则会报错,AIX平台这个值为4096。
startblock#,endblock#:这两项也是可选项。当数据文件有坏块时,可以通过设定这两项跳过坏块,这样一个数据文件可以分多行写。
3.3.2 举例:
3.3.2.1 通过v$datafile生成control.dul的一个有用脚本
SQL> set trimspool on SQL> set pagesize 0 SQL> set linesize 256 SQL> set feedback off SQL> col name format a200 SQL> spool control.dul SQL> select ts#,rfile#,name from v$datafile; SQL> spool off SQL> exit Cat $ cat control.dul SQL> select ts#,rfile#,name from v$datafile; 0 1 /yang/oradata/orcl/system01.dbf 1 2 /yang/oradata/orcl/undotbs01.dbf 3 3 /yang/oradata/orcl/example01.dbf 4 4 /yang/oradata/orcl/indx01.dbf 5 5 /yang/oradata/orcl/tools01.dbf 6 6 /yang/oradata/orcl/users01.dbf 6 7 /yang/oradata/orcl/users02.dbf SQL> spool off
Control.dul标红这两行需要去掉。
3.3.2.2 control.dul格式示例
示例1:标准格式
6 7 /yang/oradata/orcl/users02.dbf
示例2:假定数据文件users02大小为4094M(4094M去掉2M的文件头),每个数据块大小为8K,该数据文件中223019数据块出现corrupt,可以通过startblock#与endblock#把这个223019数据块跳过。
6 7 /yang/oradata/orcl/users02.dbf 1 223018
6 7 /yang/oradata/orcl/users02.dbf 223020 524032
示例3:AIX平台设定extra block offset,4096为offset值。
6 7 /dev/rusers01 4096
下一篇:DUL流程详解