PRM-DUL是开放的ORACLE DUL 软件,点击下面的链接下载PRM-DUL
DUL FOR LINUX平台(已更新为PRM-DUL)
DUL FOR Windows平台 (已更新为PRM-DUL)
Oracle DUL Data Unloader数据恢复工具信息汇总
大约从DUL 9开始,Bernard van Duijnen为了限制外界使用DUL,所以给DUL加上了软件时间锁,即他会定期编译不同平台上的DUL(DUL基于C语言编写)并定期上传到ORACLE 内部的DUL workspace(基于stbeehive的空间),Oracle Support可以使用内部VPN登陆后下载。就是说 好比bernard.van.duijnen 在10月1日发布了一个版本,日期锁是30天,那么这个版本到11月1日基本就失效了, DUL不是简单的读OS时间,所以改OS时间是没用的。 因为Oracle的datafile里也记录了一个当前时间,所以DUL读的是datafile里的时间。 一般用户不可能为了用DUL去改那个时间。
注意由于bernard.van.duijnen同学不提供HP-UX平台上的DUL,所以DUL没有HP-UX的对应版本。
同时早期的Oracle DUL版本用在现在的版本10g、11g、12c的数据库基本是用不了了,因为太老了。 在美国使用DUL是被严格控制的,在中国国内的话 基本就是Oracle ACS 高级客户服务部门对外在用,购买ORACLE ACS现场服务的价格还是很贵的。
附件为一个Oracle ACS提供DUL 服务的介绍文档(当然原厂现场服务是比较昂贵的,且前提是用户已经每年购买了PS标准服务,否则甚至无法购买ACS高级服务的现场服务):
DUL – DATA RECOVERY UNLOADER DataSheet
http://www.askmaclean.com/wp-content/uploads/2014/01/DUL.pdf
DUL 10的英文版使用手册:
DUL User’s and Configuration Guide V10.2.4.27
http://www.askmaclean.com/wp-content/uploads/2014/01/DUL-Users-and-Configuration-Guide-V10.2.4.27.pdf
DUL可以从已经损坏严重的数据库中抽取数据, DUL可以直接扫描Oracle Datafile数据文件,并识别表头块segment header,访问Extent盘区信息,并从中读取实际行数据。 后续DUL能生成SQLLDR形式的导入文件,或者EXP格式的DMP文件。
如果SYSTEM表空间数据文件还在,那么 DUL读取Oracle数据字典。否则DUL采取采用的形式实际读取行,并根据内部算法判断字段类型,字段长度。
DUL可以基本上处理所有的常见行类型,包括常规行、迁移行、链式行、多盘区和簇表等;处理这些行时不需要额外人工介入。跨平台抽取也是OK的。 DUL直接从Oracle Datafile抽取数据,而无需Oracle数据库实例。 其实施脏读,假设每个事务均已经提交。 DUL不检测是否需要做介质恢复,即便是损坏的数据块也可以读出。 支持DMT和LMT表空间。 由于是脏读,所以DUL恢复数据后一般建议由应用验证数据。
兼容性方面DUL可以处理从不同操作系统上拷贝过来的数据文件。支持大多数数据库结构: 链式行、迁移行、hash/index 簇,LONG,RAW,ROWID,DATE,Number,多FreeList,高水位,NULL等等。 DUL 兼容ORACLE 6,7,8和9以及10g 11g 12c。
诗檀软件(Maclean 所在的公司)开发了DUL的同类产品 ,PRM-DUL。 在DUL的基础上引入了图形化界面GUI和DataBridge(数据无需落地成为SQLLDR文件,直接像DBLINK一样传输到目标数据库)等功能;同时由于PRM-DUL是基于JAVA编写的,所以可以跨所有平台,包括HP-UX。
PRM-DUL的免费版本下载:
http://parnassusdata.com/sites/default/files/ParnassusData_PRMForOracle_3206.zip
PRM-DUL的使用手册 http://www.parnassusdata.com/sites/default/files/ParnassusData%20Recovery%20Manager%20For%20Oracle%20Database%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C%20v0.3.pdf
PRM-DUL的免费版本默认每张表只能抽取一万行数据,如果你的数据库很小以至于没有超过一万行数据的表,那么可以直接使用免费的PRM-DUL。 如果你的数据库较大且数据十分重要,那么可以考虑购买企业版的PRM-DUL,企业版PRM-DUL 针对一套数据库提供一个License软件使用许可证,一个License的价格是7500元人民币(含17%增值税)。
同时PRM-DUL还提供部分免费的License:
免费开放几个PRM-DUL 企业版License Key
如果你的Oracle数据库恢复case在使用DUL后仍搞不定,那么可以考虑通过服务恢复:
诗檀软件目前提供几乎所有场景的Oracle恢复情况,包括:数据库无法打开,表被误DROP、TRUNCATE、DELETE等,ASM Diskgroup无法MOUNT等。
PRM-DUL 基于JAVA开发,这保证了PRM可以跨平台运行,无论是AIX、Solaris、HPUX等Unix平台, Redhat、Oracle Linux、SUSE等Linux平台,还是Windows平台上均可以直接运行PRM。
PRM-DUL支持的操作系统平台:
Platform Name | Supported |
AIX POWER | Yes |
Solaris Sparc | Yes |
Solaris X86 | Yes |
Linux X86 | Yes |
Linux X86-64 | Yes |
HPUX | Yes |
MacOS | Yes |
PRM-DUL目前支持的数据库版本
ORACLE DATABASE VERSION | Supported |
Oracle 7 | Yes |
Oracle 8 | Yes |
Oracle 8i | Yes |
Oracle 9i | Yes |
Oracle 10g | Yes |
Oracle 11g | Yes |
Oracle 12c | Yes |
PRM-DUL目前支持的多语言:
语言 | 字符集 | 对应的编码 |
中文 简体/繁体 | ZHS16GBK | GBK |
中文 简体/繁体 | ZHS16DBCS | CP935 |
中文 简体/繁体 | ZHT16BIG5 | BIG5 |
中文 简体/繁体 | ZHT16DBCS | CP937 |
中文 简体/繁体 | ZHT16HKSCS | CP950 |
中文 简体/繁体 | ZHS16CGB231280 | GB2312 |
中文 简体/繁体 | ZHS32GB18030 | GB18030 |
日文 | JA16SJIS | SJIS |
日文 | JA16EUC | EUC_JP |
日文 | JA16DBCS | CP939 |
韩语 | KO16MSWIN949 | MS649 |
韩语 | KO16KSC5601 | EUC_KR |
韩语 | KO16DBCS | CP933 |
法语 | WE8MSWIN1252 | CP1252 |
法语 | WE8ISO8859P15 | ISO8859_15 |
法语 | WE8PC850 | CP850 |
法语 | WE8EBCDIC1148 | CP1148 |
法语 | WE8ISO8859P1 | ISO8859_1 |
法语 | WE8PC863 | CP863 |
法语 | WE8EBCDIC1047 | CP1047 |
法语 | WE8EBCDIC1147 | CP1147 |
德语 | WE8MSWIN1252 | CP1252 |
德语 | WE8ISO8859P15 | ISO8859_15 |
德语 | WE8PC850 | CP850 |
德语 | WE8EBCDIC1141 | CP1141 |
德语 | WE8ISO8859P1 | ISO8859_1 |
德语 | WE8EBCDIC1148 | CP1148 |
意大利语 | WE8MSWIN1252 | CP1252 |
意大利语 | WE8ISO8859P15 | ISO8859_15 |
意大利语 | WE8PC850 | CP850 |
意大利语 | WE8EBCDIC1144 | CP1144 |
泰语 | TH8TISASCII | CP874 |
泰语 | TH8TISEBCDIC | TIS620 |
阿拉伯语 | AR8MSWIN1256 | CP1256 |
阿拉伯语 | AR8ISO8859P6 | ISO8859_6 |
阿拉伯语 | AR8ADOS720 | CP864 |
西班牙语 | WE8MSWIN1252 | CP1252 |
西班牙语 | WE8ISO8859P1 | ISO8859_1 |
西班牙语 | WE8PC850 | CP850 |
西班牙语 | WE8EBCDIC1047 | CP1047 |
葡萄牙语 | WE8MSWIN1252 | CP1252 |
葡萄牙语 | WE8ISO8859P1 | ISO8859_1 |
葡萄牙语 | WE8PC850 | CP850 |
葡萄牙语 | WE8EBCDIC1047 | CP1047 |
葡萄牙语 | WE8ISO8859P15 | ISO8859_15 |
葡萄牙语 | WE8PC860 | CP860 |
PRM-DUL支持的表存储类型:
表存储类型 | Supported |
Cluster Table簇表 | YES |
索引组织表,分区或非分区 | YES |
普通堆表,分区或非分区 | YES |
普通堆表 启用基本压缩 | YES(Future) |
普通堆表 启用高级压缩 | NO |
普通堆表 启用混合列压缩 | NO |
普通堆表 启用加密 | NO |
带有虚拟字段virtual column的表 | NO |
链式行、迁移行 chained rows 、migrated rows | YES |
注意事项: 对于virtual column、11g optimized default column而言 数据抽取可能没问题,但会丢失对应的字段。 这2个都是11g之后的新特性,使用者较少。
PRM-DUL支持的数据类型
数据类型 | Supported |
BFILE | No |
Binary XML | No |
BINARY_DOUBLE | Yes |
BINARY_FLOAT | Yes |
BLOB | Yes |
CHAR | Yes |
CLOB and NCLOB | Yes |
Collections (including VARRAYS and nested tables) | No |
Date | Yes |
INTERVAL DAY TO SECOND | Yes |
INTERVAL YEAR TO MONTH | Yes |
LOBs stored as SecureFiles | Future |
LONG | Yes |
LONG RAW | Yes |
Multimedia data types (including Spatial, Image, and Oracle Text) | No |
NCHAR | Yes |
Number | Yes |
NVARCHAR2 | Yes |
RAW | Yes |
ROWID, UROWID | Yes |
TIMESTAMP | Yes |
TIMESTAMP WITH LOCAL TIMEZONE | Yes |
TIMESTAMP WITH TIMEZONE | Yes |
User-defined types | No |
VARCHAR2 and VARCHAR | Yes |
XMLType stored as CLOB | No |
XMLType stored as Object Relational | No |
PRM-DUL对ASM的支持
功能 | Supported |
支持直接从ASM中抽取数据,无需拷贝到文件系统上 | YES |
支持从ASM中拷贝数据文件 | YES |
支持修复ASM metadata | YES |
支持图形化展示ASM黑盒 | Future |
以下 为ORACLE DUL 工具使用手册:
ORACLE DUL 的原理和功能列表:
DUL是一个独立的C程序,它直接从数据文件的表中检索行。 Oracle的RDBMS软件完全不被使用。 DUL进行脏读,它假定每个事务被提交。它也不检查/是否需要完成介质恢复。
DUL旨在检索无法用其他方法检索的数据。它不是EXP,SQL *加等等的替代选择,而是最后的方案。不用于正常的生产环境。
在使用DUL之前,你必须知道RDBMS有许多隐藏的功能可以强制打开坏数据库。无记录的init.ora参数和事件可以用于跳过前滚,禁用回滚,禁用特定SMON行动,推进数据库scn等等。
数据库可以被破坏,但单独的数据块必须是100%正确。在所有导出进行检查时,确保块没有损坏并属于正确的数据段。如果扫描时遇到损坏的块,一个错误信息被打印在加载程序(loader)文件和标准输出。导出将继续下一行或块。
cluster/表/索引中的行
DUL能且只能导出索引/表/cluster中数据。它不会转储触发器,存储过程,也不会创建表或视图的SQL脚本。 (但描述它们的数据字典表可以被导出)。该数据将被导出为在适合SQL * Loader或IMP的格式。同时,SQL * Loader的匹配控制文件也会生成。
DUL可以导出索引和索引组织表。索引的导出能用来确定表应该有多少行或标识缺失的行。
支持跨平台导出。数据库可以从与DUL-主机不同的操作系统被复制。 (迄今所涉及的数据库/系统:Sequent/ptx, Vax Vms, Alpha Vms, MVS, HP9000/8xx, IBM AIX, SCO Unix, Alpha OSF/1, Intel Windows NT)。
在“init.dul”中的配置参数必须进行修改,以匹配原始平台和O / S,而非导出执行的平台。
DUL不会转储,运行或挂起不论数据库的破坏有多严重;(几乎)支持所有Oracle功能
对于所有数据库结构的面支持:行链接,行迁移,散列/索引集群,longs,raws,行id,日期,数字,多空闲列表组(multiple free list groups),段高水位(segment high water mark),NULLs,显示NULL列尾部,无限扩展,Oracle8的新数据块布局,分区表。
后来增加的有lobs,压缩索引,9iR2压缩表。可变数组(varray)和抽象数据类型ADTs(用户定义的对象)在SQL * Loader模式下被部分支持。
ASM是完全支持的,文件可以从ASM磁盘组中提取。不使用装载的ASM实例,磁盘直接访问。支持非默认的ASM分配单元大小。
使用unexp命令套件,数据可以从导出的转储文件中恢复。Unpump的一些初步工作已完成,以支持数据pump文件。
DUL能用于Oracle 6以上版本。 DUL已通过从6.0.26到10.2的所有版本。即使旧版数据块header布局(6.0.27.2前)也支持。
DUL本质上是一个单一字节的应用程序。它的命令解析器不理解多字节字符,但导出任何多字节的数据库是可以的。对于所有可能情况都有解决方法。
DUL可转换为UTF8。这是为了存储在UTF16的 NCLOBS。
MLSLABELS
不支持受信任的Oracle多级安全标贴。
(LONG)RAW
DUL可以导出(long)raws。目前在SQL * Loader中合适的格式来保存所有的long raws。所以long raws和blobs可以在这两种模式下被导出。
ORACLE8对象选项和LOBS
尚不支持嵌套表,如果需要请告知我来添加。支持varray和ADT,以及储存为核心lob的。 在SQL * Loader模式和EXP模式下都支持CLOBS,NCLOBS。 BLOBS在EXP模式下最好处理,在SQL * Loader模式下产生的十六进制格式当前未能正确加载。
通过ANSI-C编译器,DUL可以移植到任何操作系统。 DUL已经被移植到许多UNIX变体,VMS和WindowsNT。目前,所有构建都使用gcc和Linux的交叉编译环境完成。
对Oracle RDBMS内部的良好掌握是成功地使用DUL的必要前提。例如数据服务器内部(DSI)文档和教程提供一个良好的基础。甚至还有专门的DUL模块。
配置文件
针对DUL有两个配置文件。 “init.dul”包含所有的配置参数。 (缓存大小,header布局的详细内容,oracle数据块大小,输出文件格式)在控制文件中,“control.dul”,数据库的数据文件名和asm磁盘可以被指定。
可用数据字典
如果组成SYSTEM表空间的数据文件可用,那Oracle数据字典就可用。Oracle分配给这些文件的数字和你给定的名称(不需要是Oracle知道的原始名称),必须列入“control.dul”文件。您还需要包括文件数和其他表空间的文件名,这些表空间是最终想要导出表及其数据。不包含这些文件不会影响数据字典导出步骤,但会影响之后的表导出。
步骤如下:
这导出所有可用的数据库表。 (除了用户SYS)。
unload user SCOTT;
如果SYSTEM表空间的数据文件不可用,那么虽然可以unload 导出数据,但USER,TABLE和COLUM名称是未知的。识别表会是艰巨的任务。但它可以(并已经)被完成。你需要深入了解你的应用程序和应用程序表。列类型可以由DUL猜测,但表和列名丢失了。来自同一数据库但旧了几周的任何SYSTEM表空间可以有很大的帮助!DUL使用的多数信息不改变。 (只有dataobj#是在truncate或索引重建过程中)
步骤如下:
为了便于寻找丢失的表:在seen_tab.dat和seen_col.dat扫描的统计信息可以被加载到一个全新的数据库。如果你要重建表(但愿创建表的脚本仍可用),那么通过两个SQL * Plus脚本(fill.sql和getlost.sql),“丢失”表的结构信息可以匹配到“可见”表被扫描的信息。
DDL(DUL描述语言)导出语句概述
DUL使用类似SQL的命令界面。有导出区段,表,用户或整个数据库的DDL语句。所需的数据字典信息可以在DDL语句中指定或取自先前导出的数据字典。以下三个语句将导出DEPT表。如果数据字典和区段地图可用,最常见的形式是:
UNLOAD TABLE scott.dept;
所有相关信息也能在语句中指定:
REM Columns with type in the correct order
REM The segment header loaction in the storage clause
UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));
Oracle版本6:
REM version 6 data blocks have segment header location in each block ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE; UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));
Oracle 7:
REM Oracle7 data blocks have object id in each block
ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE; UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( OBJNO 1501 );
DUL输出格式
只有完好无损的行会被写入输出文件。对它来说,各行是缓存的。buffer的大小可以通过init.dul的参数BUFFER来更改。高BUFFER参数不等同于较快的速度,它应该大到足以容纳一个完整的行。不完整或损坏的行不会被写出。 init.dul参数FILE_SIZE_IN_MB可用于将输出(在适当的边界)分割成多个文件,每个文件可以单独加载。
有三种不同的输出格式模式
生成的文件与由EXP生成的表模式导出完全不同!该文件是IMP能加载的最小格式。每个表中将生成单独的IMP可加载文件。它是单一的表转储文件。它包含一个header,一个insert table语句和表数据。表补助grant,存储子句,或触发器将不被包括在内。一个最小的create table语句被包含在内(无存储子句,只有列名和没有精度的类型)。在生成的header中文件中的字符集指示是V6类型。它被设置为表示基于ASCII的字符集。
要启用导出模式, 将init.dul参数EXPORT_MODE设置为TRUE。
由于生成的伪转储文件不包含字符集信息集NLS_LANG以匹配原始数据库。在导出模式,不进行字符集转换。
SQL * Loader模式
数据在此模式要么完全不能转换,要么全部被转换为UTF8,前提是设置了LDR_OUTPUT_IN_UTF8。在混合字符集环境中此设置是必需的,因为一个数据文件的内容必须有一个单独的字符集。<\ p>
在加载数据时,你可能需要设置NLS_LANG以匹配原始数据库,从而防止不必要的字符集转换。
在两种SQL * Loader输出格式中,列将被空格分隔并被双引号括起来。数据中的任何双引号将增加一倍。SQL * Loader会识别这点并只加载一个。使用init.dul参数LDR_ENCLOSE_CHAR,你能将包围列的字符从双引号更改为任何想要的字符。
有两种类型的物理记录模式:
数据流模式
在流模式下没什么特别的,每条记录后会有换行符打印出来。这是紧凑模式,可用于数据不包含换行符的情况。要启用数据流模式,设置LDR_PHYS_REC_SIZE = 0
init.dul
固定的物理记录
如果数据可包含换行符,这个模式是必不可少的。一个逻辑记录和一个完整的行可以由多个物理记录组成。默认的记录长度为81,这很适合VT220的屏幕。物理记录大小可用init.dul的LDR_PHYS_REC_SIZE指定。
输出文件名
生成的文件名是:owner name_table name.ext。IMP可加载文件的扩展名为“.dmp”。“.dat”和“.ctl”被用于SQL * Loader数据文件和控制文件。为了防止变量替换和其他不好的影响,奇怪的字符被剥离。(只有字母数字和’_’被允许)。
如果设置了FILE参数,生成的名称将是FILEnnn.ext。如果文件系统不支持足够长的文件名,可以用这个方法处理。 (旧的窗口,6.3文件名格式)
一些DUL INTERNALS
要求信息
要从数据库块中导出表数据必须了解以下信息:
二进制HEADER
在块头的C-Structs不被直接复制,它们通过特殊功能被检索。结构成员的所有补偿都被编入DUL。这种方法使跨平台导出实现。(在HP导出MVS创建的数据文件)除了字节顺序,至今只有四个布局类型被发现。
机器依赖
(数据库)机器依赖用以下参数配置:
导出数据字典
如果数据字典的文件存在且未破坏,DUL可以导出数据库的数据字典。对于要使用的数据字典,内部表必须首先导出至外部文件:(USER $,OBJ $,TAB $和COL $)。bootstrap命令将找到并导出所需的表。
DDL(DUL描述语言)规范
DDL(DUL描述语言)规范
DDL(DUL描述语言)规范 [ ALTER SESSION ] SET init.dul parameter = value ; Most parameters can be changed on the fly. BOOTSTRAP [LOCATE | GENERATE | COMPLETE | UNLOAD Bootstrap$ segment header block address ]; Bootstraps the data dictionary. Default is COMPLETE. LOCATE finds and unloads the bootstrap$ table. GENERATE builds a ddl file based on inforation in the cache. COMPLETE is in fact LOCATE, followed by GENERATE (two times) COMMIT; Writes the changed block to the data file. CREATE BLOCK INDEX index_name ON device ;
块索引包含在损坏的文件系统中找到的有效Oracle块的地址。用于合并多个磁盘映像或从损坏的文件系统导出。只有在极端的文件系统损坏情况下很有用。
DESCRIBE owner_name . table_name ; DUMP [ TABLESPACE tablespace_no ] [ FILE file_no ] [ BLOCK block_no ] [ LEVEL level_no ] ; Not a complete blockdump, mainly used for debugging. The block address is remembered. EXTRACT asm file name to output file name ; Copies any ASM file from a disk group to the file system. (there was a problem with online redologs this needs more testing) MERGE block_index INTO [ segment ];
合并命令使用索引文件中的信息来定位文件数和对象id的组合的可能数据块,每个候选块与在数据文件中的当前块进行比较。如果当前块是坏的,或有一个更旧的scn,候选人将被写入数据文件。这只有在极端的文件系统损坏情况下很有用。
REM any_text_you_like_till_End_Of_Line : comment REM NOT allowed inside ddl statements. ( To avoid a two layer lexical scan). ROLLBACK; # Cancels the UPDATE statements. SHOW DBA dba ; # dba -> file_no block_no calculator | DBA rfile_no block_no ; # file_no block_no -> dba calculator | SIZES ; # show some size of important structs | PARAMETER; # shows the values of all parameters | LOBINFO; # lob indexes found with SCAN DATABASE | DATAFILES; # summary of configured datafiles | ASM DISKS; # summary of configured asm disks | ASM FILES; # summary of configured datafiles on asm | ASM FILE cid # extent information for asm file UNEXP [TABLE] [ owner . ] table name ( column list ) [ DIRECT ] DUMP FILE dump file name FROM begin offset [ UNTIL end offset ] [ MINIMUM minimal number of columns COLUMNS ] ; To unload data from a corrupted exp dump file. No special setup or configuration is required, just the compatible parameter. The start offset should be where a row actually begins. UNPUMP To unload data from a corrupted expdp (datapump) dump file. This is still work in progress, the basic commands work but rather complex to use. Contact me if this is needed. UNLOAD DATABASE; UNLOAD USER user_name; UNLOAD [TABLE] [ schema_name . ] table_name [ PARTITION( partition_name ) ] [ SUBPARTITION( sub_partition_name ) ] [ ( column_definitions ) ] [ cluster_clause ] [ storage_clause ] ; UNLOAD EXTENT table_name [ ( column_definitions ) ] [ TABLESPACE tablespace_no ] FILE extent_start_file_number BLOCK extent_start_block_number BLOCKS extent_size_in oracle_blocks ; UNLOAD LOB SEGMENT FOR [ schema_name . ] table_name [ ( column name ) ] ; UNLOAD LOB SEGMENT STORAGE ( SEGOBJNO data obj#) ; UPDATE [ block_address ] SET UB1|UB2|UB4 @ offset_in_block = new_value ; UPDATE [ block_address ] SET block element name = new_value ; Now and then we can repair something. Patches the current block and dumps it. You can issue multiple UPDATE commands. Block is not written yet, use COMMIT to write. storage_clause ::= STORAGE ( storage_specification [ more_storage_specs ] ) storage_specification ::= OBJNO object_id_number | TABNO cluster_table_number | SEGOBJNO cluster/data_object_number /* v7/v8 style data block id */ | FILE data_segment_header_file_number /* v6 style data block id */ BLOCK data_segment_header_block_number ) | any_normal_storage_specification_but_silently_ignored SCAN DATABASE;
扫描所有数据文件的所有块。生产了两个或三个文件:
DDL(DUL描述语言)概述
UNLOAD EXTENT和UNLOAD TABLE规则:
extent map 盘区地图
UNLOAD TABLE要求一个extent map 盘区地图。在99.99%的情况下,段头中的extent map 盘区地图是可用的。在罕见的0.01%的情况下,段头丢失。可以用扫描数据库命令创建一个区段地图。仅当参数USE_SCANNED_EXTENT_MAP被设为TRUE时,自生成的区段地图才在导出时被使用。
所有数据块有它们所属一些段的ID。但是V6和V7之间有根本区别。由Oracle版本6创建的数据块有段头块的地址。由Oracle7创建的数据块在header中有段对象ID。
列定义
列定义必须指定列存储在段中的顺序,由col$.segcol#指定。这不需要与在CREATE TABLE语句中指定的列顺序相同。集群列被移到前面,long移到后面。使用ALTER TABLE命令添加到表的列总是最后保存。
导出单个区段
UNLOAD EXTENT可用于导出一个或多个相邻块。要导出的区段必须用STROEAGE子句指定:要指定单个区段,使用:STORAGE(EXTENTS(FILE fno BLOCK bno BLOCKS #blocks))(FILE和BLOCK指定第一个块,BLOCKS 区段大小)
DUL具体列类型
有两个额外的DUL特定数据类型:
在SQL * Loader模式还有更多DUL特定的数据类型:
识别USER $,OBJ $,$ TAB和COL $
DUL使用与RDBMS相同的bootstrap程序。即它使用系统数据文件头的root dba来定位bootstrap$ 表。由于版本不同,root dba可能是包含bootstrap$地址的兼容段位置,或较新版本中是bootstrap$表本身的地址。bootstrap$表被导出,它的内容是分析以查找头四表(USER $,OBJ $,$ TAB和COL $)。其他表是基于头四个表的信息被导出的。
SCAN 扫描命令概述
SCAN TABLES和SCAN EXTENTS扫描相同的信息,并生成类似的输出。所有行的所有列都被检查。每一列收集以下统计数据:
这些统计被组合并有一种列类型被提出。使用该建议,五行被导出显示结果。这些统计数据转储到两个文件(seen_tab.dat和seen_col.dat)。有SQL * Loader和SQL * Plus脚本可以自动完成识别过程的一部分。 (目前称为getlost选项)。
描述describe
有一个描述命令。它会显示表格的字典信息,在DUL的字典缓存中可用。
DUL启动顺序
在启动过程中,DUL经过以下步骤:
init.dul中可以指定的DUL 参数
ALLOW_TRAILER_MISMATCH
BOOLEAN
强烈不推荐使用,不太会产生更多的行。只有在你完全理解它的意思及为什么想使用时才能使用。跳过正确块trailer的检查。在这个测试中失败的块是损坏的碎片。但这样省去了修补一些块的麻烦。
ALLOW_DBA_MISMATCH
BOOLEAN
强烈不推荐使用,不太会产生更多的行。只有在你完全理解它的意思及为什么想使用时才能使用。跳过正确块trailer的检查。在这个测试中失败的块是损坏的碎片。但这样省去了修补一些块的麻烦。
ALLOW_OTHER_OBJNO
BOOLEAN
如果你的字典比你的数据文件更旧,那数据对象ID对于被truncate的表有所不同。当这个参数设为true,它会发出警告,但使用来自段头的值。所有其他块都被全面检查。这只用于特例。
ASCII2EBCDIC
BOOLEAN
(var)char字段必须从 EBCDIC 转译为 ASCII。(针对在ASCII主机上导出MVS数据库)
BUFFER
NUMBER (字节)
在导出和SQL * Loader模式中使用的行输出缓冲区(buffer)的大小。它在各行被首先存储到该缓冲区中。只有没有错误的完整行被写入输出文件。
COMPATIBLE
NUMBER
数据库版本,有效值为 6,7,8或9。必须指定参数。
CONTROL_FILE
TEXT
DUL 控制文件名(默认:“ control.dul”)。
DB_BLOCK_SIZE
NUMBER
字节表示的Oracle块大小(最大32K)
DC_COLUMNS
NUMBER
DC_OBJECTS
NUMBER
DC_TABLES
NUMBER
DC_USERS
NUMBER
dul 字典缓存大小。如果其中一个过低,高速缓存将被自动调整大小。
EXPORT_MODE
BOOLEAN
使用export 导出模式或 SQL*Loader 模式。
FILE
TEXT
(转储或数据)文件名生成的基础。对类似8.3 DOS的文件系统使用。
FILE_SIZE_IN_MB
NUMBER (Megabytes)
最大转储文件大小。转储文件被分割成多个部分。每个文件都有一个完整的头,并能被单独加载。
LDR_ENCLOSE_CHAR
TEXT
括起SQL* Loader模式中字段的字符。The character to enclose fields in SQL*Loader mode.
LDR_PHYS_REC_SIZE
NUMBER
生成的loader数据文件的物理记录大小。
LDR_PHYS_REC_SIZE = 0没有固定的记录,每个记录以一个换行符结束。
LDR_PHYS_REC_SIZE > 2: 固定的记录大小。
MAX_OPEN_FILES
在操作系统级别同时保持开放的数据文件最大#。
OSD_BIG_ENDIAN_FLAG
机器语言表示的字节顺序。Big Endian一开始也被称为MSB。 DUL根据在运行的机器设置默认值。要了解这个被称为Big Endian的原因,阅读格列佛游记。
OSD_DBA_FILE_BITS 以位表示的DBA中文件编号大小。更精确的说是文件号的低序部分的大小。 OSD_FILE_LEADER_SIZE bytes/blocks added before the real oracle file header block OSD_C_STRUCT_ALIGNMENT C 结构成员对齐(0,16或23)。默认的32对于大多数端口是正确的。 OSD_WORD_SIZE 一个机器字的大小总是32,除了MS/DOS(16) PARSE_HEX_ESCAPES Boolean 默认 FALSE 在解析时,在字符串使用\\xhh十六进制转义序列。如果设置为true,则奇怪的字符可以使用转义序列来指定。该功能也用于指定多字节字符。 USE_SCANNED_EXTENT_MAP BOOLEAN 导出表时,在ext.dat使用扫描好的区段地图。一般算法在段头使用区段地图。只有当一些段头丢失或不正确时,该参数才有用。 WARN_RECREATE_FILES BOOLEAN (TRUE) 如果现有的文件被覆盖,设置为FALSE以取消警告信息。 WRITABLE_DATAFILES BOOLEAN (FALSE) DUL的一般使用只会读取数据库文件。然而,UPDATE和 SCAN RAW DEVICE也将写出。参数能防止有意外损坏。 示例 init.dul : # sample init.dul configuration parameters # these must be big enough for the database in question # the cache must hold all entries from the dollar tables. dc_columns = 200000 dc_tables = 10000 dc_objects = 10000 dc_users = 40 # OS specific parameters osd_big_endian_flag = false osd_dba_file_bits = 10 osd_c_struct_alignment = 32 osd_file_leader_size = 1 # database parameters db_block_size = 8k # loader format definitions LDR_ENCLOSE_CHAR = " LDR_PHYS_REC_SIZE = 81 配置端口相关的参数 从RDBMS版本10G 开始,osd参数易于配置。通常,所有参数都可以使用其默认值。唯一可能要注意的是osd_big_endian_flag,在原始数据库平台与当前机器不同的情况下进行跨平台导出时,如果osd_big_endian_flag设置不正确,当检查文件头时让会在启动时被检测。 已知参数集合 对于预10G数据库没有在OSD的OSD维基页面列表(操作系统Dependend),几乎每一个平台参数已知参数列表。如果你的平台不在列表中,你可以使用下面的建议确定的参数。 (然后请通知我,让我可以将它们添加到列表中。) osd_big_endian_flag big endian 或 little endian(机器表示的字节顺序):HP,SUN和大型机通常big endian:OSD_BIG_ENDIAN_FLAG = TRUE。 DEC和Intel平台是little endian :OSD_BIG_ENDIAN_FLAG = FALSE。默认值对DUL正在运行的平台是正确的。 这点没有标准的技巧,以下在UNIX系统上可能有效: echo dul | od -x If the output is like: 0000000 6475 6c0a 0000004 You are on a big endian machine (OSD_BIG_ENDIAN_FLAG=TRUE). If you see: 0000000 7564 0a6c 0000004 This is a little endian machine (OSD_BIG_ENDIAN_FLAG=FALSE). osd_dba_file_bits 在DBA用于文件号的低位部分的位数量。执行以下查询: SQL> select dump(chartorowid('0.0.1')) from dual; Typ=69 Len=6: 8,0,0,0,0,0 -> osd_dba_file_bits = 5 (SCO) Typ=69 Len=6: 4,0,0,0,0,0 -> osd_dba_file_bits = 6 (Sequent , HP) Typ=69 Len=6: 1,0,0,0,0,0 -> osd_dba_file_bits = 8 (NCR,AIX) Typ=69 Len=6: 0,16,0,0,0,0 -> osd_dba_file_bits = 12 (MVS) Typ=69 Len=10: 0,0,0,0,0,64,0,0,0,0 osd_dba_file_bits = 10 (Oracle8) OSD_C_STRUCT_ALIGNMENT 在数据文件头的结构布局。 0:在C-结构(VAX/ VMS只)成员之间没有填充16:一些韩国ticom机和MS/ DOS32:结构成员按成员大小排列。 (所有其他包括ALPHA / VMS)检查以下查询: SELECT * FROM v$type_size WHERE type IN ( 'KCBH', 'KTNO', 'KCBH', 'KTBBH', 'KTBIT', 'KDBH' , 'KTECT', 'KTETB', 'KTSHC') ; 一般情况下,会出现osd_c_struct_alignment=32以及如下: 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 SIZE -------- -------- -------------------------------- ---------- K KTNO TABLE NUMBER IN CLUSTER 1 KCB KCBH BLOCK COMMON HEADER 20 KTB KTBIT TRANSACTION VARIABLE HEADER 23 KTB KTBBH TRANSACTION FIXED HEADER 42 KDB KDBH DATA HEADER 14 KTE KTECT EXTENT CONTROL 39 KTE KTETB EXTENT TABLE 8 KTS KTSHC SEGMENT HEADER 7 8 rows selected. 如果有一个不同的列表,这将需要一些主要黑客攻击和嗅探,还可能对DUL有重大变化。 (电子邮件[email protected]) osd_file_leader_size 在Oracle文件头前的块/字节数。 Unix数据文件有一个额外的领先块(文件大小,块大小幻数)大量(>100)被看作是一个字节偏移,少数被看作Oracle块号。 Unix : osd_file_leader_size = 1 Vms : osd_file_leader_size = 0 Desktop : osd_file_leader_size = 1 (or 512 for old personal oracle) Others : Unknown ( Use Andre Bakker's famous PATCH utility to find out) An Oracle7 file header block starts with the pattern 0X0B010000. 你可以在可选的第三个字段的control.dul中添加一个额外的字节偏移(如在原始设备的AIX或DEC UNIX数据文件) 控制文件语法规范 控制文件(默认名称“control.dul”)用于指定ASM磁盘,块索引和数据文件名。control的格式已被扩展。 目前在DUL控制文件中有三种类型的定义。在单独的行中的每个条目。 ASM磁盘必须先于ASM文件。 control_file_line ::= asm_disk_spec | file_piece_spec | block_index_spec 如果兼容是10或更高,你也可以指定ASM磁盘。它对于指定设备名称通常足够。所有属性都是由头部检查自动检索。当头部检查是不可能时才需要完整的语法,用于有损坏的header的磁盘。语法是: DISK device name [ disk group options ] disk group option ::= GROUP disk group name | DISK_NO disk number in group | F1B1 File1 Block1 location 块索引是在损坏的文件系统上访问Oracle块的一种方式。通常,损坏的文件系统没有被全部删除,它不是空的。由于oracle块的特定布局,it is possible to datablocks an store their location in the block index。参见 create block index命令。block_index_name是一个普通的标识符,它用于构建一个唯一的文件名。 BLOCK INDEX block_index_name 每个条目可以包含一个数据文件的一部分。最小单位是一个数据块。这种的话,将对于DUL太大的数据文件分割成多个部分是可能的,其中每个部分小于2GB。 一般指定的文件名就足够了。即使对于单个块。如果compatible为10或更高,文件号和表空间号将从文件头读取。 如果指定的细节与文件头不同,DUL会给出一个警告,但使用你的定义。这是为了能在文件损坏的头块导出文件。对于调试,可以转储文件头。 可选的额外leader 偏移是一个额外的字节偏移,它将被添加到该数据文件的所有lseek() 操作。这样就可以跳过一些AIX原始设备额外的4K块,或在原始设备上Tru64d 额外的64K。 file_piece_spec ::= [ [ tablespace_no ] relative_file_number]data_file_name [ optional extra leader offset ] [ startblock block_no ] [ endblock block_no ] 示例 # AIX version 7 example with one file on raw device 1 /usr/oracle/dbs/system.dbf 8 /dev/rdsk/data.dbf 4096 # Oracle8 example with a datafile split in multiple parts, each part smaller than 2GB 0 1 /fs1/oradata/PMS/system.dbf 1 2 /tmp/huge_file_part1 startblock 1 endblock 1000000 1 2 /tmp/huge_file_part2 startblock 1000001 endblock 2000000 1 2 /mnt3/huge_file_part3 startblock 2000001 endblock 2550000 # ASM disks for two disk groups disk /media/maxtor/asm/dgn1 disk /media/maxtor/asm/dgn2 disk /media/maxtor/asm/dgn3 disk /media/maxtor/asm/dgn4 disk /media/maxtor/asm/dgodd # system datafile in the first asm disk group +DGN/db102/datafile/system.257.621616979 # users datafile in a different disk group +DGODD/db102/datafile/users.257.621616683 # a so called big file tablespace, use 1024 for the file# 8 1024 /home/oracle/v102/dbs/bigfilets # Or let DUL find out itself from the header /home/oracle/v102/dbs/bigfilets # one tablespace with a different block size /home/oracle/v102/dbs/ts16k.dbf block_size 16k # or let DUL find out by header inspection /home/oracle/v102/dbs/ts16k.dbf
示例导出会话:可用于DUL的数据字典 1. 创建一个合适的“init.dul” 2. 创建control.dul sqlplus /nolog connect / as sysdba startup mount set trimspool on pagesize 0 linesize 256 feedback off column name format a200 spool control.dul select ts#, rfile#, name from v$datafile; exit edit the result For Oracle8 a different query must be used: select ts#, rfile#, name from v$datafile; 1. 启动DUL和bootstrap; $ dul Data UnLoader 10.2.1.16 - Oracle Internal Only - on Thu Jun 28 11:37:24 2007 with 64-bit io functions Copyright (c) 1994 2007 Bernard van Duijnen All rights reserved. Strictly Oracle Internal use Only DUL> bootstrap; Probing file = 1, block = 377 . unloading table BOOTSTRAP$ 57 rows unloaded DUL: Warning: Dictionary cache DC_BOOTSTRAP is empty Reading BOOTSTRAP.dat 57 entries loaded Parsing Bootstrap$ contents DUL: Warning: Recreating file "dict.ddl" Generating dict.ddl for version 10 OBJ$: segobjno 18, file 1 TAB$: segobjno 2, tabno 1, file 1 COL$: segobjno 2, tabno 5, file 1 USER$: segobjno 10, tabno 1, file 1 Running generated file "@dict.ddl" to unload the dictionary tables . unloading table OBJ$ 52275 rows unloaded . unloading table TAB$ 1943 rows unloaded . unloading table COL$ 59310 rows unloaded . unloading table USER$ 70 rows unloaded Reading USER.dat 70 entries loaded Reading OBJ.dat 52275 entries loaded and sorted 52275 entries Reading TAB.dat 1943 entries loaded Reading COL.dat 59310 entries loaded and sorted 59310 entries Reading BOOTSTRAP.dat 57 entries loaded ... Some more messages for all the other TABLES ... Database character set is WE8ISO8859P1 Database national character set is AL16UTF16 DUL> unload user SCOTT; About to unload SCOTT's tables ... . unloading table EMP 14 rows unloaded 示例导出会话:无法用于DUL的数据字典 1. 创建一个合适的“init.dul”(见配置指南) 2. 创建control.dul见上文 3. 扫描数据库的段头和区段: $ dul UnLoader: Version 2.0.0.0 - Very Restricted on Tue May 16 11:10:16 1995 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. DUL> scan database; data file 1 20480 blocks scanned data file 4 7680 blocks scanned data file 5 512 blocks scanned DUL>quit 1. 重启DUL和扫描找到的表获得列统计,这生成了大量输出: echo scan tables \; | dul > scan.out& [ many lines here] Object id 1601 table number 0 UNLOAD TABLE T1601_0 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER, C5 DATE , C6 NUMBER, C7 NUMBER, C8 NUMBER ) STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530)); Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid% 1 14 3 0% 0% 0% 100% 100% 0% 0% 2 14 6 0% 100% 100% 100% 14% 0% 21% 3 14 9 0% 100% 100% 100% 14% 0% 0% 4 14 3 7% 0% 0% 100% 100% 0% 0% 5 14 7 0% 0% 0% 0% 0% 100% 0% 6 14 3 0% 0% 0% 100% 100% 0% 0% 7 14 2 71% 0% 0% 100% 100% 0% 0% 8 14 2 0% 0% 0% 100% 100% 0% 0% "7369" "SMITH" "CLERK" "7902" "17-DEC-1980 AD 00:00:00" "800" "" "20" "7499" "-0.000025253223" "SALESMAN" "7698" "20-FEB-1981 AD 00:00:00" "1600" "30+ 0" "30" "7521" "WARD" "SALESMAN" "7698" "22-FEB-1981 AD 00:00:00" "1250" "500" "30" "7566" "JONES" "MANAGER" "7839" "02-APR-1981 AD 00:00:00" "2975" "" "20" "7654" "MARTIN" "SALESMAN" "7698" "28-SEP-1981 AD 00:00:00" "1250" "1400" "30" [ many more lines here ] 这看着很眼熟,使用以上信息和你对emp表的了解来编写: UNLOAD TABLE emp ( empno number, ename char, job char, mgr number, hiredate date, sal number, comm number deptno number) STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530)); 1. 用这个语句来导出emp: $ dul UnLoader: Version 2.0.0.0 - Very Restricted on Tue May 16 11:46:33 1995 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Loaded 350 segments Loaded 204 extents Extent map sorted DUL> UNLOAD TABLE emp ( empno number, ename char, job char, mgr number, DUL 2> hiredate date, sal number, comm number deptno number) DUL 3> STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530)); . unloading table EMP 14 rows unloaded DUL>quit 示例导出会话:不正确的init.dul参数 错误的 osd_dba_file_bits大小 这会产生类似如下的输出。通常这不应该发生,因为你应该创建一个演示数据库,并通过DUL记录的(HTML页)查询进行检查。 在DBA的失配是只在文件号(括号内第一号)的部分。第二个数字,块号,是正确的。 Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:40:33 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [4][2] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][3] DBA in block mismatch [4][3] DUL: Warning: Bad cache layer header file#=1, block#=3 ...........and etc.......... 错误的osd_file_leader_size 这可能会造成类似如下的输出,但还有许多其他可能。在这里,我们block off号是固定的。In this case we are a fixed number of blocks off.文件号是正确的。块号的差是恒定的: Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:44:23 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [1][3] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][3] DBA in block mismatch [1][4] DUL: Warning: Bad cache layer header file#=1, block#=3 ...........and etc.......... 错误的osd_c_struct_alignment 这可能会产生类似如下的输出: Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:46:10 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. . unloading table OBJ$ DUL: Warning: file# 0 is out of range DUL: Warning: Cannot read data block file#=0, block# = 262145 OS error 2: No such file or directory DUL: Warning: file# 0 is out of range DUL: Warning: Cannot read data block file#=0, block# = 262146 OS error 2: No such file or directory ...........and etc.......... 错误的db_block_size 当DB_BLOCK_SIZE设置过小时会生成以下输出。正确值是4096,而设置为2048。通常情况下,此参数值应取自Oracle实例的init.ora文件中,且将无法正确设置。 Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Thu Sep 4 12:38:25 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [513][1159680] DUL: Warning: File=1, block 2: illegal block version 2 DUL: Warning: Block[1][2] Illegal block type[0] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][4] DBA in block mismatch [1][2] DUL: Warning: File[1]Block[4]INCSEQ mismatch[90268!=0] DUL: Warning: Bad cache layer header file#=1, block#=4 DUL: Warning: Block[1][6] DBA in block mismatch [1][3] DUL: Warning: File[1]Block[6]INCSEQ mismatch[139591710!=86360346] DUL: Warning: Bad cache layer header file#=1, block#=6 ...........and etc.......... QUOTE MISSING 如果收到以下错误,这是由于数据字典表“USER$,OBJ$,$ TAB和COL$”没有被正确生成。要解决这个错误,简单地删除所有dictv6.ddl或dictv7.ddl创建.dat和.ctl文件并重启。 Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:49:30 1997 Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:49:30 1997 DUL: Error: Quote missing 从损坏的EXP转储文件拯救数据 - UNEXP教程 如果你不了解EXP转储文件的结构任何东西,这就比较困难。以下是一个快速解释。除了文件头,转储文件有识别各个部分的标记。在每个表部分会有SQL语句。最有趣的部分是create table语句,接下来是插入到表语句。插入语句后直接跟绑定信息,(列数,以及每列的类型和绑定长度和其他一些信息)。接下来是实际的列。每列之前是两个字节长度,后跟实际列数据。可能较长的列有几个技巧。列数据的结尾以特殊的长度标记OXFFFF标志。行的开头没有标记。损坏后的重新同步是试错。损坏一般不能立即检测到。该格式与DIRECT导出略有不同,所以你必须要对DIRECT导出使用DIRECT选项。指定的偏移量是一个行的开头。一般来说第一个直接在绑定数组之后,但为最佳的灵活性,你可以从行数据的任何地方开始。 第一步是扫描转储文件来找到偏移和SQL语句。每个输出行从项目被找到的偏移位置开始。 DUL> scan dump file expdat.dmp; 0: CSET: 1 (US7ASCII) # Character set info from the header 3: SEAL EXPORT:V10.02.01 # the Seal - the exp version tag 20: DBA SYSTEM # exp done as SYSTEM 8461: CONNECT SCOTT # section for user SCOTT 8475: TABLE "EMP" # complete create table staement 8487: CREATE TABLE "EMP" ("EMPNO" NUMBER(4, 0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4, 0), "HIREDATE" DATE, "SAL" NUMBER(7, 2), "COMM" NUMBER(7, 2), "DEPTNO" NUMBER(2, 0)) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "USERS" LOGGING NOCOMPRESS # Insert statement 8829: INSERT INTO "EMP" ("EMPNO", "ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM", "DEPTNO") VALUES (:1, :2, :3, :4, :5, :6, :7, :8) # BIND information 8957: BIND information for 8 columns col[ 1] type 2 max length 22 col[ 2] type 1 max length 10 cset 31 (WE8ISO8859P1) form 1 col[ 3] type 1 max length 9 cset 31 (WE8ISO8859P1) form 1 col[ 4] type 2 max length 22 col[ 5] type 12 max length 7 col[ 6] type 2 max length 22 col[ 7] type 2 max length 22 col[ 8] type 2 max length 22 Conventional export # Conventional means NOT DIRECT 9003: start of table data # Here begins the first row 现在从create table语句和直接/常规信息和列数据的开头创建unexp语句。 UNEXP TABLE "EMP" ("EMPNO" NUMBER(4, 0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4, 0), "HIREDATE" DATE, "SAL" NUMBER(7, 2), "COMM" NUMBER(7, 2), "DEPTNO" NUMBER(2, 0)) dump file expdat.dmp from 9003; Unloaded 14 rows, end of table marker at 9670 # so we have our famous 14 rows 这将创建普通SQL * Loader文件和匹配的控制文件。在输出文件中一个额外的列被添加,这是与行的状态有关。 AP表示行是部分的,(缺失一些列)R指重新同步,这是一个再同步之后的第一行。 O表示重叠,之前的一行有错误,但新行与另一行部分重叠。 目录 ~~~~~~~~~~~~~~~~~ 1.简介 2.使用DUL 2.1创建一个适当的init.dul文件 2.2创建control.dul文件 2.3导出对象信息 2.4调用DUL 2.5重建数据库 3.如何重建存储在数据字典的对象定义? 4当段头块被损坏时,如何导出数据? 5. 当文件头块被损坏时,如何导出数据? 6.如何导出数据,而无需系统表空间? 7.附录A:哪里可以找到可执行文件? 8.参考 1.简介 ~~~~~~~~~~~~~~~ 本文档解释了如何使用DUL,而不是对Bernard的数据导出能力的完整解释。 本文件仅供内部使用,不应在任何时候给予客户,DUL应始终被分析师使用或在分析师监督下使用。 DUL(数据导出)尝试从Oracle数据库中检索无法检索的数据。这不是导出工具或 SQL * Loader的替代选择。该数据库可能被破坏,但一个单独的数据块必须是100%正确的。在所有导出时,块会被检查,以确保块没有损坏且属于正确的段。如果一个损坏的块被DUL检测到,错误信息会被打印到loader文件,并输出到标准输出,但是这不会终止下一行或块的导出。 2.使用DUL ~~~~~~~~~~~~ 首先,你必须获得存在于数据块的对象所需的信息,这些统计将被加载到DUL字典以导出数据库对象。 这个信息是从在数据库创建时被创建的USER $,OBJ $,$ TAB和COL $表中检索的 ,它们可以基于这一事实:由于SQL,BSQ的刚性性质,对象号在这些表是固定的而被导出。 DUL可以在系统的系统表空间中找到信息,因此,如果(多个)数据文件不存在,(多个)表数据文件必须包含在控制文件中,参见第6章。 2.1创建相应的“init.dul”文件 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ REM平台指定参数(NT) REM能获取的最常见平台的一列参数。 osd_big_endian_flag=false osd_dba_file_bits=10 osd_c_struct_alignment=32 osd_file_leader_size=1 osd_word_size = 32 REM DUL字典缓存的大小。如果其中某一个过低,启动将失败。 dc_columns=2000000 dc_tables=10000 dc_objects=1000000 dc_users=400 dc_segments=100000 控制文件的位置和文件名,默认值是control.dul 在当前目录control_file = D:\Dul\control_orcl.dul 数据库块大小,可以在init.ora中的文件中找到,或在服务器管理器中执行“show parameter %db_block_size%” 被检索到 (svrmgr23/ 30 /l)将该参数更改为损坏数据块的块大小。 db_block_size=4096。 当数据需要导出/导入格式,它可以/必须被指定。 这将创建Oracle导入工具适用的文件,虽然生成的文件与由EXP工具生成的表模式导出完全不同。 它是有一个创建表结构语句和表数据的单个表转储文件。 grants,存储子句,触发器不包括在这个转储文件中! export_mode=true REM兼容参数可以被指定且可以是6,7或8 compatible=8 该参数是可选的并能在REM不支持的长文件名(e.g. 8.3 DOS)的平台,或当文件格式DUL使用 “owner_name.table_name.ext”不可接受时被指定。 在这里,转储文件会类似dump001.ext,dump002.ext,等。 file = dump 完整的列表可在HTML部分“DUL参数”获取,虽然这init.dul文件在大多数情况可行,且包含所有正确参数以成功完成导出。 2.2 创建“control.dul”文件 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 你需要对有关逻辑表空间和物理数据文件有一定了解,或你可以在数据库被加载时进行以下查询: Oracle 6, 7 ———– > connect internal > spool control.DUL > select * from v$dbfile; > spool off Oracle 8 ——– > connect internal > spool control.DUL > select ts#, rfile#, name from v$datafile; > spool off 如果需要的话,编辑spool文件和变化,数据文件的位置和stripe out不必要的信息,如表头,反馈行,等... 示例控制文件像这样: Edit the spool file and change, if needed, the datafile location and stripe out unnecessary information like table headers, feedback line, etc… A sample control file looks something like this : REM Oracle7 control file 1 D:\DUL\DATAFILE\SYS1ORCL.DBF 3 D:\DUL\DATAFILE\DAT1ORCL.DBF 7 D:\DUL\DATAFILE\USR1ORCL.DBF REM Oracle8 control file 0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF 1 2 D:\DUL\DATAFILE\USR1ORCL.DBF 1 3 D:\DUL\DATAFILE\USR2ORCL.DBF 2 4 D:\DUL\DATAFILE\DAT1ORCL.DBF 注:每个条目可以包含一个数据文件的一部分,当你需要拆分对于DUL太大的数据文件时,这就有用了,这样每个部分就小于比方说2GB了。 例如 : REM Oracle8 其中一个数据文件被分割成多部分,每部分小于1GB! 0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF 1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1 endblock 1000000 1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1000001 endblock 2000000 1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 2000001 endblock 2550000 2.3 Unload the object information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以适当DDL(DUL描述语言)脚本启动BUL工具。由于数据库版本不同,有3个可用脚本来导出USER$,$ OBJ,TAB$和COL$表。 Oracle6 :> dul8.exe dictv6.ddl Oracle7 :> dul8.exe dictv7.ddl Oracle8 :> dul8.exe dictv8.ddl Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Jun 22 22:19: Copyright (c) 1994/1999 Bernard van Duijnen All rights reserved. Parameter altered Session altered. Parameter altered Session altered. Parameter altered Session altered. Parameter altered Session altered. . unloading table OBJ$ 2271 rows unloaded . unloading table TAB$ 245 rows unloaded . unloading table COL$ 10489 rows unloaded . unloading table USER$ 22 rows unloaded . unloading table TABPART$ 0 rows unloaded . unloading table IND$ 274 rows unloaded . unloading table ICOL$ 514 rows unloaded . unloading table LOB$ 13 rows unloaded Life is DUL without it 这将 USER$, OBJ$, TAB$ and COl$ 数据字典表的数据导出到 SQL*Loader 文件,这不能被处理到导入格式的转储文件中。 , this can not be manipulated into dump files of the import format. 参数 export_mode = false 被硬编码到ddl脚本且不能更改为值“true”,因为这会导致DUL产生错误而失败: . unloading table OBJ$ DUL: Error: Column “DATAOBJ#” actual size(2) greater than length in column definition(1) ………….etc…………… 2.4 调用DUL ~~~~~~~~~~~~~~ 在交互模式下启动DUL,你也可以准备一个包含所有ddl命令以导出数据库必要数据的脚本。我会在本文档中描述最常用的命令,但不是完整的可指定参数列表。完整的列表可以在 “DDL描述”部分找到。 DUL> unload database; => 这将导出整个数据库表(包括sys'tables) DUL> unload user ; => 这将导出所有特定用户所拥有的表。 DUL> unload table ; => 这将卸载由用户名拥有的指定表 DUL> describe ; => 将表示表列以及指定用户所拥有的(多个)数据文件的指向。will represent the table columns with there relative pointers to the datafile(s) owned by the specified user. DUL> scan database; =>扫描所有数据文件的所有块。 生成两个文件: 1:找到的段头的seg.dat信息(索引/集群/表) (对象ID,文件号和块号)。 2:连续的表/集群的数据块的ext.dat信息。 (对象ID(V7),文件和段头的块号(V6),文件号和第一个块的块号,块的数量,表数量) DUL> scan tables; =>使用seg.dat和ext.dat作为输入。 扫描所有数据段中的所有表(一个头块和至少匹配至少一个表的一个区段)。 2.5重建数据库 ~~~~~~~~~~~~~~~~~~~~~~~~ 创建新的数据库,并使用导入或SQL * Loader来恢复被DUL检索到的数据。需要注意的是,当你只导出表结构数据时,索引,grants,PL / SQL和触发器将不再在新的数据库中存在。为了获得与之前数据库的完全相同的副本,你需要重新运行表,索引,PL / SQL等的创建脚本。 如果你没有这些脚本,那么你将需要执行在文档第3部分描述的步骤。 3.如何重建存储在数据字典的对象定义 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~ 要通过DUL重建PL / SQL(程序包,过程,函数或触发器),grants,索引,约束或存储子句(旧的表结构)是可以的,但就是有点棘手。您需要使用DUL导出相关的数据字典表,然后加载这些表到一个健康的数据库,一定要使用与SYS或(系统)不同的用户。加载损坏数据库的数据字典表到健康数据库字典可能也会破坏健康的数据库。 示例从损坏的数据库检索pl/sql packages / procedures /functions的详情: 1)按照在“使用DUL”一节中的步骤解释并导出数据字典表“source$” 2)创建一个新的用户登录到一个健康数据库,并指定所需的默认和临时表空间。 3)将连接,资源, imp_full_database授权给新用户。 4)导入/加载表“source$”到新创建的模式: 例如:imp80 userid=newuser/passw file=d:\dul\scott_emp.dmp log=d:\dul\impemp.txt full=y 5)现在,您可以从表查询以在损坏的数据库中重建pl/sql packages / procedures /functions。在WebIv可以找到产生这样的PL / SQL创建脚本。 相同的步骤可以用于重建索引,约束,和存储参数,或者为相应的用户重新授权。请注意,你总是需要使用某种类型的脚本,可以重建对象并包括损坏的数据库版本的所有功能。例如:当损坏的数据库是7.3.4版本,你有几个位图索引,如果你会使用支持7.3.2版本或之前的脚本,那么你将无法成功重建位图索引! 4. 当段头块被损坏时,如何导出数据 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ 当DUL不能以正常方式检索数据块信息,它可以扫描数据库来创建其自己的段/区段地图。要从数据文件导出数据,扫描数据库的过程是必要的。 (为了说明这个例子,我根据段头块复制一个空块) 1)创建一个适当的“init.dul”(见2.1)和“control.dul”(见2.2)的文件。 2)导出表。这将失败,并指出段头块有损坏: DUL> unload table scott.emp; . unloading table EMP DUL: Warning: Block is never used, block type is zero DUL: Error: While checking tablespace 6 file 10 block 2 DUL: Error: While processing block ts#=6, file#=10, block#=2 DUL: Error: Could not read/parse segment header 0 rows unloaded 3)运行扫描数据库命令: DUL> scan database; tablespace 0, data file 1: 10239 blocks scanned tablespace 6, data file 10: 2559 blocks scanned 4)向DUL说明它应该使用自己的生成的区段地图,而不是段头信息。 DUL> alter session set use_scanned_extent_map = true; Parameter altered Session altered. DUL> unload table scott.emp; . unloading table EMP 14 rows unloaded 5. 当数据文件头块损坏时,如何导出数据 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ 在你打开数据库时,数据文件头块的损坏总是会列出。这不像一个头段块的损坏(见第4点),其中的数据库可以成功打开,且当你进行表查询时,损坏会列出。DUL从这种情况中恢复没有问题,尽管有其他恢复这种情况的方法,如为数据文件头块打补丁。 你将收到如下错误: ORACLE instance started. Total System Global Area 11739136 bytes Fixed Size 49152 bytes Variable Size 7421952 bytes Database Buffers 4194304 bytes Redo Buffers 73728 bytes Database mounted. ORA-01122: database file 10 failed verification check ORA-01110: data file 10: ‘D:\DATA\TRGT\DATAFILES\JUR1TRGT.DBF’ ORA-01251: Unknown File Header Version read for file number 10 6.如何卸载数据,而无需系统表空间 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 如果数据文件不能用于系统表空间,导出仍可继续,但对象信息无法从数据字典表USER $,OBJ $,$ TAB和COL $检索。所以所有者名称,表名和列名不会被加载到DUL字典。识别表会是一项艰巨的任务,且这里需要对RDBMS内部有很好的了解。 首先,你需要对你的应用和它的表有很好的了解。 列类型可以有DUL猜测,但表和列名都将丢失。 任何同一个数据库旧的系统表空间(可能是几周前的)可以是很大的帮助! 1)如上述的步骤1和2,创建 “init.dul”文件和“control.dul”文件。在这种情况下,控制文件将包含所有你想要恢复的数据文件,但不需要系统表空间的信息。 2)然后你调用DUL并输入以下命令: DUL> scan database; data file 6 1280 blocks scanned 这将创建区段和段地图。也许DUL命令解释程序也将被终止。 3)重新调用DUL命令解释器并执行以下操作: Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Aug 03 13:33: Copyright (c) 1994/1999 Oracle Corporation, The Netherlands. All rights res Loaded 4 segments Loaded 2 extents Extent map sorted DUL> alter session set use_scanned_extent_map = true; DUL> scan tables; (or scan extents;) Scanning tables with segment header Oid 1078 fno 6 bno 2 table number 0 UNLOAD TABLE T_O1078 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN ) STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 2)); Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid% 1 4 2 0% 0% 0% 100% 100% 0% 0% 2 4 10 0% 100% 100% 100% 0% 0% 0% 3 4 8 0% 100% 100% 100% 0% 0% 50% “10” “ACCOUNTING” “NEW YORK” “20” “RESEARCH” “DALLAS” “30” “SALES” “CHICAGO” “40” “OPERATIONS” “BOSTON” Oid 1080 fno 6 bno 12 table number 0 UNLOAD TABLE T_O1080 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER, C5 DATE, C6 NUMBER, C7 NUMBER, C8 NUMBER ) STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 12)); Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid% 1 14 3 0% 0% 0% 100% 100% 0% 0% 2 14 6 0% 100% 100% 100% 0% 0% 21% 3 14 9 0% 100% 100% 100% 0% 0% 0% 4 14 3 7% 0% 0% 100% 100% 0% 0% 5 14 7 0% 0% 0% 0% 0% 100% 0% 6 14 3 0% 0% 0% 100% 100% 0% 0% 7 14 2 71% 0% 0% 100% 100% 0% 0% 8 14 2 0% 0% 0% 100% 100% 0% 0% “7369” “SMITH” “CLERK” “7902” “17-DEC-1980 AD 00:00:00″ “800” “” “20” “7499” “ALLEN” “SALESMAN” “7698” “20-FEB-1981 AD 00:00:00″ “1600” “300” “30” “7521” “WARD” “SALESMAN” “7698” “22-FEB-1981 AD 00:00:00″ “1250” “500” “30” “7566” “JONES” “MANAGER” “7839” “02-APR-1981 AD 00:00:00″ “2975” “” “20” “7654” “MARTIN” “SALESMAN” “7698” “28-SEP-1981 AD 00:00:00″ “1250” “1400” “30” Note : it might be best that you redirect the output to a logfile since commands like the “scan tables” can produce a lot of output. On Windows NT you can do the following command : C:\> dul8 > c:\temp\scan_tables.txt scan tables; exit; 4)从步骤3的输出中找到丢失的表;如果你仔细看上面的输出会发现,unload语法已经给出,但表的名称将是格式T_0 ,列名称将是格式的C ;数据类型不会精确匹配之前的数据类型。 特别查找像“Oid 1078 fno 6 bno 2 table number 0”的字符串,其中: oid = object id, will be used to unload the object 对象id,会被用于导出对象 fno = (data)file number (数据)文件号 bno = block number 块号 5)使用“unload table”命令导出找出的表: DUL> unload table dept (deptno number(2), dname varchar2(14), loc varchar2(13)) storage (OBJNO 1078) Unloading extent(s) of table DEPT 4 rows. 评论: DUL盘头副本 盘头副本 盘头副本 最近有ASM磁盘头的额外副本。通过使用kfed与修复选项,此副本可以用来修复真正的头。 位置 此副本被存储为PST的最后一个块。这意味着它在分配单元1的最后一个块(原来是au 0的块0)。分配单位的默认大小为为1M,元数据块的默认大小为4K,这表示每个au中有256块。所以,通常副本在au1 block 254(ASM从零计数,原始的在分配单元0块0) kfed修复 确定唯一的问题是与丢失/损坏的磁盘头后,该修复程序很简单,只要: $ kfed repair 如果su大小为非标准的,以上会失败,显示如下: KFED-00320: Invalid block num1 = [3] , num2 = [1] , error = [type_kfbh] 但这是预料之中的,且没有任何损害。你只需要指定正确的au大小。例如4MB AU的命令是: $ kfed repair ausz=4194304 DUL DUL将检查/使用头复制(总是?或者只在主头损坏的情况下?)如果头损坏,但副本是好的,警告使用kfed? 参考 Bug 5061821 OS工具可以摧毁ASM磁盘头fixed 11.2.0.1,11.1.0.7,10.2.0.5和更高。 注意417687.1在现有的一个磁盘头损坏后创建一个新的ASM磁盘头 rdbms/src/client/tools/kfed/kfed.c DUL导出扫描的lob 我们的想法是直接从LOB段导出LOB。 我们需要弄清楚: 1. 它是CLOB还是BLOB 2. 对于CLOB,它的字符集,单字节或UCS16,字节大小 3. 块大小,在头中的lob page#是一个fat page number 4. 缺失页应当被发出为全零 5. 大小未知,只需要剥离trailing zeroes(但对于字节大小)? 实施的变更: 1.添加LOB段ID来扫描lob页面信息,因为大多数属性适用于段。即扫描的lob页缓存的布局是:segid,lobid,fatpageno(chunk#),version wrap, vsn base, ts#, file#, block# 要做的事: 1.导出所有LOB的命令。一个LOB段提供命令中所有的常用属性。 2.从LOB段指定lobid,可选的大小,和可选的DBA列表中导出单个lob的命令 3.分析生成导出LOB段命令的命令 4.分析生成从段中导出每个LOB命令的命令 需要考虑的事项: 1. 更改 file#, block# 为单个dba?pro no calculations, contra more difficult to read? 我正与客户在处理一个数据打捞作业。从DUL网站下载的DUL工具不能正常工作! dul4x86-linux.tar.gz给出错误:version ‘GLIBC_2.11’ not found dul4i386-linux.as3.tar.gz给出错误:You need a more recent DUL version for this os.你需要一个较新的版本DUL这个操作系统。 客户端Linux版本:2.6.32-400.33.2.el5uek 请帮忙!!! Linux有两个版本,这是第二个,被正常启动的。由于内建复制的保护,您必须确保从Bernard的网站上下载最新的版本。如果你确实有最新的下载,那么只有Bernard可以重新编译并重新分配一个新的可执行版本。 DUL大约每45天失效。 我们处在关键时刻,需要DUL从一个production down降数据库中提取数据。 - 数据库在NOARCHIVELOG模式/ Windows 64位平台。 - 由于go life,没有可用的数据库备份 - 数据库较小,但非常重要。 - 从早晨开始有介质故障损坏了除真正客户数据的数据文件之外的所有数据库的数据文件。 - 根据每db验证工具输出,系统表空间100%损坏。 - 任何地方都没有系统表空间的备份,甚至测试系统是作为新的数据库创建的,因此对象ID,rfile号是不一样的。 我们尝试了以下内容: 1. 使用系统数据文件从生产中导出数据(由于系统数据文件被破坏,无法bootstrap) 2. 使用系统数据文件从TEST中导出数据(成功bootstrap,但无法导出,因为不匹配rfile#,TS#,和对象ID ..预想到的结果,但值得一试) 3. 仅使用实际数据的数据文件导出数据,成功生成scaned_tables,并且我们已向客户请求提供表的列表来map,但我不确定他们能否提供清晰信息。 感谢提供任何建议,类似于: - 有没有什么办法来修复损坏的系统表空间的数据文件,并用它进行数据导出。 - 或者,有没有办法从TEST使用系统数据文件(不同的数据库作为新安装),其中rfile#, ts#,和对象id的错配。
DUL is a standalone C program that directly retrieves rows from tables in data files. The Oracle RDBMS software is NOT used at all. DUL does dirty reads, it assumes that every transaction is committed. Nor does it check/require that media recovery has been done.
DUL is intended to retrieve data that cannot be retrieved otherwise. It is NOT an alternative for EXP, SQL*Plus etc. It is meant to be a last resort, not for normal production usage.
Before you use DUL you must be aware that the rdbms has many hidden features to force a bad database open. Undocumented init.ora parameters and events can be used to skip roll forward, to disable rollback, disable certain SMON actions, advance the database scn and more.
The database can be corrupted, but an individual data block used must be 100% correct. During all unloading checks are made to make sure that blocks are not corrupted and belong to the correct segment. If during a scan a bad block is encountered, an error message is printed in the loader file and to standard output. Unloading will continue with the next row or block.
DUL can and will only unload index/table/cluster data. It will NOT dump triggers, stored procedures nor create sql scripts for tables or views. (But the data dictionary tables describing them can be unloaded). The data will be unloaded in a format suitable for SQL*Loader or IMP. A matching control file for SQL*Loader is generated as well.
DUL can unload indices and index organized tables. Index unload is usefull to determine how many rows a table should have or to identify the missing rows.
Cross-platform unloading is supported. The database can be copied from a different operating system than the DUL-host. (Databases/systems done so far: Sequent/ptx, Vax Vms, Alpha Vms, MVS, HP9000/8xx, IBM AIX, SCO Unix, Alpha OSF/1, Intel Windows NT).
The configuration parameters within “init.dul” will have to be modified to match those of the original platform and O/S rather than the platform from which the unload is being done.
DUL will not dump, spin or hang no matter how badly corrupted the database is.
Full support for all database constructs: row chaining, row migration, hash/index clusters, longs, raws, rowids, dates, numbers, multiple free list groups, segment high water mark, NULLS, trailing NULL columns, and unlimited extents, new block layout of Oracle8, partitioned tables.
Later additions are lobs, compressed indexes, 9ir2 compressed tables. Varrays and ADTs (user defined objects) are partly supported in sql*loader mode.
ASM is fully supported, files can be extracted from an asm disk group. No mounted ASM instance is used, the disks are accessed directly. Non default asm allocation unit sizes are supported.
Data can be recovered from export dump files with the unexp command suite. Some initial work has been done for unpump to support data pump files.
DUL should work with all versions starting oracle 6. DUL has been tested with versions from 6.0.26 up to 10.2. Even the old block header layout (pre 6.0.27.2) is supported.
DUL itself is essentially a single byte application. The command parser does not understand multi byte characters, but it is possible to unload any multi byte database. For all possible caveats there is a work around.
DUL can optionally convert to UTF8. This is for NCLOBS that are stored in UTF16.
Multi Level Security Lables of trusted oracle are not supported.
DUL can unload (long) raws. Nowadays there is suitable format in SQL*Loader to preserve all long raws. So Long raws and blobs can be unloaded in both modes.
Nested tables are not yet supported, if they are needed let me know and it will be added. Varrays and ADTs are supported, also those that are stored as a kernel lob. CLOBS, NCLOBS are supported both in SQL*Loader mode and in exp mode. BLOBS are best handled in exp mode, the generated hex format in SQL*Loader mode is not loaded correctly currently.
DUL can be ported to any operating system with an ANSI-C compiler. DUL has been ported to many UNIX variants, VMS and WindowsNT. Currently all builds are done using gcc and a cross compiler environment on Linux
A good knowledge of the Oracle RDBMS internals is a pre requisite to be able to use DUL successfully. For instance the Data Server Internals (DSI) courses give a good foundation. There is even a module dedicated to DUL
There are two configuration files for DUL. “init.dul” contains all configuration parameters. (size of caches, details of header layout, oracle block size, output file format) In the control file, “control.dul”, the database data file names and the asm disks can be specified.
The Oracle data dictionary is available if the data files which made up the SYSTEM TableSpace are available and useable. The number which Oracle assigned to these files and the name you have given them, which does not have to be the original name which Oracle knew, must be included in the “control.dul” file. You also need to eventually include the file numbers and names of any files from other TableSpaces for which you wish to eventually unload TABLES and their data. The lack of inclusion of these files will not affect the data dictionary unload step but it will affect later TABLE unloading.
Steps to follow:
If data files are not available for the SYSTEM TableSpace the unload can still continue but USER, TABLE and COLUM names will not be known. Identifying the tables can be an overwhelming task. But it can be (and has been) done. You need in depth knowledge about your application and the application tables. Column types can be guessed by DUL, but table and column names are lost. Any old SYSTEM tablespace from the same database but weeks old can be of great help!. Most of the information that DUL uses does not change. (only the dataobj# is during truncate or index rebuild)
Steps to follow:
To ease the hunt for the lost tables: the scanned statistical information in seen_tab.dat and seen_col.dat can be loaded into a fresh database. If you recreate the tables ( Hopefully the create table scripts are still available) then structure information of a “lost” table can be matched to the “seen” tables scanned information with two SQL*Plus scripts. (fill.sql and getlost.sql).
DUL uses an SQL like command interface. There are DDL statements to unload extents, tables, users or the entire database. Data dictionary information required can be specified in the ddl statements or taken from the previously unloaded data dictionary. The following three statements will unload the DEPT table. The most common form is if the data dictionary and the extent map are available:
UNLOAD TABLE scott.dept;
All relevant information can be specified in the statement as well:
REM Columns with type in the correct order REM The segment header loaction in the storage clause UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));
Oracle version 6:
REM version 6 data blocks have segment header location in each block ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE; UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( EXTENTS ( FILE 1 BLOCK 1205 ));
Oracle7:
REM Oracle7 data blocks have object id in each block ALTER SESSION SET USE_SCANNED_EXTENT_MAP = TRUE; UNLOAD TABLE dept( deptno NUMBER, dname CHAR, loc CHAR) STORAGE( OBJNO 1501 );
Only complete good rows are written to the output file. For this each row is buffered. The size of the buffer can changed with the init.dul parameter BUFFER. There is no speed gained with a high BUFFER parameter, it should just be big enough to hold a complete row. Incomplete or bad rows are not written out. The FILE_SIZE_IN_MB init.dul parameter can be used to split the output (at a proper boundary) into multiple files, each file can be loaded individually.
There are three different modes of output format.
The generated file is completely different from a table mode export generated by EXP! The file is the minimal format that IMP can load. For each table a separate IMP loadable file will be generated. It is a single table dump file. It contains a header an insert table statement and the table data. Table grants, storage clauses, or triggers will not be included. An minimal create table statement is included (no storage clause just column names and types without precision). The character set indication in the file in the generated header is V6 style. It is set to mean ASCII based characterset.
To enable export mode, set the init.dul parameter EXPORT_MODE to TRUE.
As the generated pseudo dump file does not contain character set information set NLS_LANG to match that of the original database. In export mode no character set conversion is done.
The data in the is either not converted at all, or everthing is converted to UTF8 if LDR_OUTPUT_IN_UTF8 is set. This setting is required in mixed character set environments as the contents of a data file must have a single character set.<\P>
When loading the data you probably need to set NLS_LANG to match that of the original database to prevent unwanted character set conversion.
For both SQL*Loader output formats the columns will be space separated and enclosed in double quotes. Any double quote in the data will be doubled. SQL*Loader recognizes this and will load only one. The character used to enclose the columns can be changed from double quote to any character you like with the init.dul parameter LDR_ENCLOSE_CHAR.
There are two styles of physical record organization:
Nothing special is done in stream mode, a newline is printed after each record. This is a compact format and can be used if the data does not contain newline characters. To enable stream mode set LDR_PHYS_REC_SIZE = 0 in init.dul.
This mode is essential if the data can contain newlines. One logical record, one comlete row, can be composed of multiple physical records. The default is record length is 81, this fits nicely on the screen of a VT220. The physical record size can be specified with LDR_PHYS_REC_SIZE in init.dul.
The file names generated are: owner name_table name.ext. The extension is “.dmp” for IMP loadable files. “.dat” and “.ctl” are used for the SQL*Loader datafile and the control file. To prevent variable substitution and other unwanted side effects, strange characters are stripped.(Only alpha numeric and ‘_’ are allowed).
If the FILE parameter is set the generated names will be FILEnnn.ext. This possibility is a work around if the file system does not support long enough file names. (Old windows with 6.3 filename format)
To unload table data from a database block the following information must be known:
C-Structs in block headers are not copied directly, they are retrieved with specialized functions. All offsets of structure members are programmed into DUL. This approach makes it possible to cross-unload. (Unload an MVS created data file on an HP) Apart from byte order only four layout types have been found so far.
Machine dependencies (of the database) are configurable with parameters:
DUL can use the data dictionary of the database to be unloaded if the files for it exist and are uncorrupted. For the data dictionary to be used, internal tables must be unloaded first to external files: (USER$, OBJ$, TAB$ and COL$). The bootstrap command will find and unload the required tables.
[ ALTER SESSION ] SET init.dul parameter = value ; Most parameters can be changed on the fly. BOOTSTRAP [LOCATE | GENERATE | COMPLETE | UNLOAD Bootstrap$ segment header block address ]; Bootstraps the data dictionary. Default is COMPLETE. LOCATE finds and unloads the bootstrap$ table. GENERATE builds a ddl file based on inforation in the cache. COMPLETE is in fact LOCATE, followed by GENERATE (two times) COMMIT; Writes the changed block to the data file. CREATE BLOCK INDEX index_name ON device ;
A block index contains address of valid oracle blocks found in a corrupt file system. Useful to merge multiple disk images or to unload from corrupted file systems. This is only useful in extreme file system corruption scenarios.
DESCRIBE owner_name . table_name ; DUMP [ TABLESPACE tablespace_no ] [ FILE file_no ] [ BLOCK block_no ] [ LEVEL level_no ] ; Not a complete blockdump, mainly used for debugging. The block address is remembered. EXTRACT asm file name to output file name ; Copies any ASM file from a disk group to the file system. (there was a problem with online redologs this needs more testing) MERGE block_index INTO [ segment ];
The merge command uses the information in the index file to locate possible data blocks it looks for a combination of file numbers and object id, each candidate block is compared to the current block in the datafile. If the current block is bad, or has an older scn the candidate will will be written into the datafile. This is only useful in extreme file system corruption scenarios.
REM any_text_you_like_till_End_Of_Line : comment REM NOT allowed inside ddl statements. ( To avoid a two layer lexical scan). ROLLBACK; # Cancels the UPDATE statements. SHOW DBA dba ; # dba -> file_no block_no calculator | DBA rfile_no block_no ; # file_no block_no -> dba calculator | SIZES ; # show some size of important structs | PARAMETER; # shows the values of all parameters | LOBINFO; # lob indexes found with SCAN DATABASE | DATAFILES; # summary of configured datafiles | ASM DISKS; # summary of configured asm disks | ASM FILES; # summary of configured datafiles on asm | ASM FILE cid # extent information for asm file UNEXP [TABLE] [ owner . ] table name ( column list ) [ DIRECT ] DUMP FILE dump file name FROM begin offset [ UNTIL end offset ] [ MINIMUM minimal number of columns COLUMNS ] ; To unload data from a corrupted exp dump file. No special setup or configuration is required, just the compatible parameter. The start offset should be where a row actually begins. UNPUMP To unload data from a corrupted expdp (datapump) dump file. This is still work in progress, the basic commands work but rather complex to use. Contact me if this is needed. UNLOAD DATABASE; UNLOAD USER user_name; UNLOAD [TABLE] [ schema_name . ] table_name [ PARTITION( partition_name ) ] [ SUBPARTITION( sub_partition_name ) ] [ ( column_definitions ) ] [ cluster_clause ] [ storage_clause ] ; UNLOAD EXTENT table_name [ ( column_definitions ) ] [ TABLESPACE tablespace_no ] FILE extent_start_file_number BLOCK extent_start_block_number BLOCKS extent_size_in oracle_blocks ; UNLOAD LOB SEGMENT FOR [ schema_name . ] table_name [ ( column name ) ] ; UNLOAD LOB SEGMENT STORAGE ( SEGOBJNO data obj#) ; UPDATE [ block_address ] SET UB1|UB2|UB4 @ offset_in_block = new_value ; UPDATE [ block_address ] SET block element name = new_value ; Now and then we can repair something. Patches the current block and dumps it. You can issue multiple UPDATE commands. Block is not written yet, use COMMIT to write. storage_clause ::= STORAGE ( storage_specification [ more_storage_specs ] ) storage_specification ::= OBJNO object_id_number | TABNO cluster_table_number | SEGOBJNO cluster/data_object_number /* v7/v8 style data block id */ | FILE data_segment_header_file_number /* v6 style data block id */ BLOCK data_segment_header_block_number ) | any_normal_storage_specification_but_silently_ignored SCAN DATABASE;
Scans all blocks of all data files. Two or three files are generated:
SCAN DUMP FILE dump file name [ FROM begin offset ] [ UNTIL end offset ]; Scans an export dump file to produce to provide the create/insert statements and the offsets in the dump file. SCAN LOB SEGMENT storage clause ; SCAN LOB SEGMENT FOR table name [. column name] ; Scans the lob segment to produce LOBPAGE.dat information, but then for this segment only. Probably quicker and smaller. For partitioned objects use scan database. SCAN TABLES; Uses SEG.dat and EXT.dat as input. Scans all tables in all data segments (a header block and at least one matching extent with at least 1 table). SCAN EXTENTS; Uses SEG.dat and EXT.dat as input. All extents for which no corresponding segment header has been found. (Only useful if a tablespace is not complete, or a segment header is corrupt). EXIT QUIT and EOF all cause DUL to terminate.
UNLOAD TABLE requires an extent map. In 99.99% of the cases the extent map in the segment header is available. In the rare 0.01% that the segment header is lost an extent map can be build with the scan database command. The self build extent map will ONLY be used during an unload if the parameter USE_SCANNED_EXTENT_MAP is set to TRUE.
All data blocks have some ID of the segment they belong to. But there is a fundamental difference between V6 and V7. Data blocks created by Oracle version 6 have the address of the segment header block. Data blocks created by Oracle7 have the segment object id in the header.
The column definitions must be specified in the order the columns are stored in the segment, that is ordered by col$.segcol#. This is not necessarily the same order as the columns where specified in the create table statement. Cluster columns are moved to the front, longs to the end. Columns added to the table with alter table command, are always stored last.
UNLOAD EXTENT can be used to unload 1 or more adjacent blocks. The extent to be unloaded must be specified with the STORAGE clause: To specify a single extent use: STORAGE ( EXTENTS( FILE fno BLOCK bno BLOCKS #blocks) ) (FILE and BLOCK specify the first block, BLOCKS the size of the extent)
There are two extra DUL specific data types:
In SQL*Loader mode there are even more DUL specific data types:
DUL uses the same bootstrap procedure as the rdbms. That is it uses the root dba from the system datafile header to locate the bootstrap$ table. Depending on the version this root dba is either the location of the compatibility segment containing the bootstrap$ address or for the newer versions the address of the bootstrap$ table itself. The bootstrap$ table is unloaded and its contents is parsed to find the first four tables (USER$, OBJ$, TAB$ and COL$). The other tables are unloaded based on information in these first four.
SCAN TABLES and SCAN EXTENTS scan for the same information and produce similar output. ALL columns of ALL rows are inspected. For each column the following statistics are gathered:
These statistics are combined and a column type is suggested. Using this suggestion five rows are unloaded to show the result. These statistics are dumped to two files (seen_tab.dat and seen_col.dat). There are SQL*Loader and SQL*Plus scripts available to automate a part of the identification process. (Currently known as the getlost option).
There is a describe command. It will show the dictionary information for the table, available in DUL’s dictionary cache.
During startup DUL goes through the following steps:
SAMPLE init.dul :
# sample init.dul configuration parameters # these must be big enough for the database in question # the cache must hold all entries from the dollar tables. dc_columns = 200000 dc_tables = 10000 dc_objects = 10000 dc_users = 40 # OS specific parameters osd_big_endian_flag = false osd_dba_file_bits = 10 osd_c_struct_alignment = 32 osd_file_leader_size = 1 # database parameters db_block_size = 8k # loader format definitions LDR_ENCLOSE_CHAR = " LDR_PHYS_REC_SIZE = 81
Starting from rdbms version 10G osd parameters are easy to configure. Typically all parameters can be used at their defaults. The only one that might need attention is osd_big_endian_flag, when doing a cross platform unload, where the original database platform is different from the current machine. If osd_big_endian_flag is set incorrectly, it is detected at startup, when doing file header inspection.
For pre 10G databases there is a list of known parameters in the osd wiki page list of osd (Operating System Dependend) parameters for almost every platform. If your platform is not in the list you can use the suggestions below to determine the parameters. (And then please inform me so I can add them to the list.)
big endian or little endian (byte order in machine words): HP, SUN and mainframes are generally big endian: OSD_BIG_ENDIAN_FLAG = TRUE. DEC and Intel platforms are little endian: OSD_BIG_ENDIAN_FLAG = FALSE. The default is correct for the platform where DUL is running on.
There is no standard trick for this, the following might work on a unix system:
echo dul | od -x If the output is like: 0000000 6475 6c0a 0000004 You are on a big endian machine (OSD_BIG_ENDIAN_FLAG=TRUE). If you see: 0000000 7564 0a6c 0000004 This is a little endian machine (OSD_BIG_ENDIAN_FLAG=FALSE).
The number of bits in a dba used for the low order part of file number. Perform the following query:
SQL> select dump(chartorowid('0.0.1')) from dual; Typ=69 Len=6: 8,0,0,0,0,0 -> osd_dba_file_bits = 5 (SCO) Typ=69 Len=6: 4,0,0,0,0,0 -> osd_dba_file_bits = 6 (Sequent , HP) Typ=69 Len=6: 1,0,0,0,0,0 -> osd_dba_file_bits = 8 (NCR,AIX) Typ=69 Len=6: 0,16,0,0,0,0 -> osd_dba_file_bits = 12 (MVS) Typ=69 Len=10: 0,0,0,0,0,64,0,0,0,0 osd_dba_file_bits = 10 (Oracle8)
Structure layout in data file headers. 0: No padding between members in a C-struct (VAX/VMS only) 16: Some korean ticom machines and MS/DOS 32: Structure members are member size aligned. (All others including ALPHA/VMS) Check the following query:
SELECT * FROM v$type_size WHERE type IN ( 'KCBH', 'KTNO', 'KCBH', 'KTBBH', 'KTBIT', 'KDBH' , 'KTECT', 'KTETB', 'KTSHC') ;
In general osd_c_struct_alignment = 32 and the following output is expected:
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.
For VAX/VMS and Netware ONLY osd_c_struct_alignment = 0 and this output is expected:
COMPONEN TYPE DESCRIPTION SIZE -------- -------- -------------------------------- ---------- K KTNO TABLE NUMBER IN CLUSTER 1 KCB KCBH BLOCK COMMON HEADER 20 KTB KTBIT TRANSACTION VARIABLE HEADER 23 KTB KTBBH TRANSACTION FIXED HEADER 42 KDB KDBH DATA HEADER 14 KTE KTECT EXTENT CONTROL 39 KTE KTETB EXTENT TABLE 8 KTS KTSHC SEGMENT HEADER 7 8 rows selected.
If there is a different list this will require some major hacking and sniffing and possibly a major change to DUL. (Email [email protected])
Number of blocks/bytes before the oracle file header. Unix datafiles have an extra leading block ( file size, block size magic number) A large number ( > 100) is seen as a byte offset, a small number is seen as a number of oracle blocks.
Unix : osd_file_leader_size = 1 Vms : osd_file_leader_size = 0 Desktop : osd_file_leader_size = 1 (or 512 for old personal oracle) Others : Unknown ( Use Andre Bakker's famous PATCH utility to find out) An Oracle7 file header block starts with the pattern 0X0B010000.
You can add an additional byte offset in control.dul in the optional third field (for instance for AIX or DEC UNIX data files on raw device)
A control file (default name “control.dul”) is used to specify asm disks, block indexes and the data file names. The format of the control has been extended
Currently there are three types of specifications in the DUL control file. Each entry on a separate line. The asm disks must precede the asm files.
control_file_line ::= asm_disk_spec | file_piece_spec | block_index_spec
If COMPATIBLE is 10 or higher you can also specify asm disks. Its generally sufficent to specify the device name. All properties are automatically retrieved by header inspection. The full syntax is only needed when header inspection is impossible, that is for disks with corrupt headers. The syntax is:
DISK device name [ disk group options ] disk group option ::= GROUP disk group name | DISK_NO disk number in group | F1B1 File1 Block1 location
A block index is a way to access oracle blocks on corrupt file systems. In general a corrupt file system is not wiped out, its not empty. Due to the specific layout of oracle blocks it is possible to datablocks an store their location in the block index. See also the create block index command . A block_index_name is a normal identifier, it is used to construct an unique file name.
BLOCK INDEX block_index_name
Each entry can contain a part of a datafile. The smallest unit is a single data block. This way it is possible to split datafiles that are too big for DUL in parts where each part is smaller than 2GB.
In general it is sufficient to specify the file name. Even for a single block. If compatible is 10 or higher the file numbers and the tablespace numbers will be read from the file header.
If the specified details are different from the file header DUL will give a warning but use your specification. This is to be able to unload files with a corrupted header block. For debugging it is possible to dump the file header.
The optional extra leader offset is an extra byte offset, that will be added to all lseek() operations for that datafile. This makes it possible to skip over the extra 4k block for some AIX raw devices, or the extra 64K on Tru64 on raw devices
file_piece_spec ::= [ [ tablespace_no ] relative_file_number]data_file_name [ optional extra leader offset ] [ startblock block_no ] [ endblock block_no ]
# AIX version 7 example with one file on raw device 1 /usr/oracle/dbs/system.dbf 8 /dev/rdsk/data.dbf 4096
# Oracle8 example with a datafile split in multiple parts, each part smaller than 2GB 0 1 /fs1/oradata/PMS/system.dbf 1 2 /tmp/huge_file_part1 startblock 1 endblock 1000000 1 2 /tmp/huge_file_part2 startblock 1000001 endblock 2000000 1 2 /mnt3/huge_file_part3 startblock 2000001 endblock 2550000
# ASM disks for two disk groups disk /media/maxtor/asm/dgn1 disk /media/maxtor/asm/dgn2 disk /media/maxtor/asm/dgn3 disk /media/maxtor/asm/dgn4 disk /media/maxtor/asm/dgodd # system datafile in the first asm disk group +DGN/db102/datafile/system.257.621616979 # users datafile in a different disk group +DGODD/db102/datafile/users.257.621616683 # a so called big file tablespace, use 1024 for the file# 8 1024 /home/oracle/v102/dbs/bigfilets # Or let DUL find out itself from the header /home/oracle/v102/dbs/bigfilets # one tablespace with a different block size /home/oracle/v102/dbs/ts16k.dbf block_size 16k # or let DUL find out by header inspection /home/oracle/v102/dbs/ts16k.dbf
sqlplus /nolog connect / as sysdba startup mount set trimspool on pagesize 0 linesize 256 feedback off column name format a200 spool control.dul select ts#, rfile#, name from v$datafile; exit edit the result
For Oracle8 a different query must be used: select ts#, rfile#, name from v$datafile;
$ dul Data UnLoader 10.2.1.16 - Oracle Internal Only - on Thu Jun 28 11:37:24 2007 with 64-bit io functions Copyright (c) 1994 2007 Bernard van Duijnen All rights reserved. Strictly Oracle Internal use Only DUL> bootstrap; Probing file = 1, block = 377 . unloading table BOOTSTRAP$ 57 rows unloaded DUL: Warning: Dictionary cache DC_BOOTSTRAP is empty Reading BOOTSTRAP.dat 57 entries loaded Parsing Bootstrap$ contents DUL: Warning: Recreating file "dict.ddl" Generating dict.ddl for version 10 OBJ$: segobjno 18, file 1 TAB$: segobjno 2, tabno 1, file 1 COL$: segobjno 2, tabno 5, file 1 USER$: segobjno 10, tabno 1, file 1 Running generated file "@dict.ddl" to unload the dictionary tables . unloading table OBJ$ 52275 rows unloaded . unloading table TAB$ 1943 rows unloaded . unloading table COL$ 59310 rows unloaded . unloading table USER$ 70 rows unloaded Reading USER.dat 70 entries loaded Reading OBJ.dat 52275 entries loaded and sorted 52275 entries Reading TAB.dat 1943 entries loaded Reading COL.dat 59310 entries loaded and sorted 59310 entries Reading BOOTSTRAP.dat 57 entries loaded ... Some more messages for all the other TABLES ... Database character set is WE8ISO8859P1 Database national character set is AL16UTF16 DUL> unload user SCOTT; About to unload SCOTT's tables ... . unloading table EMP 14 rows unloaded
$ dul UnLoader: Version 2.0.0.0 - Very Restricted on Tue May 16 11:10:16 1995 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. DUL> scan database; data file 1 20480 blocks scanned data file 4 7680 blocks scanned data file 5 512 blocks scanned DUL>quit
echo scan tables \; | dul > scan.out& [ many lines here] Object id 1601 table number 0 UNLOAD TABLE T1601_0 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER, C5 DATE , C6 NUMBER, C7 NUMBER, C8 NUMBER ) STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530)); Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid% 1 14 3 0% 0% 0% 100% 100% 0% 0% 2 14 6 0% 100% 100% 100% 14% 0% 21% 3 14 9 0% 100% 100% 100% 14% 0% 0% 4 14 3 7% 0% 0% 100% 100% 0% 0% 5 14 7 0% 0% 0% 0% 0% 100% 0% 6 14 3 0% 0% 0% 100% 100% 0% 0% 7 14 2 71% 0% 0% 100% 100% 0% 0% 8 14 2 0% 0% 0% 100% 100% 0% 0% "7369" "SMITH" "CLERK" "7902" "17-DEC-1980 AD 00:00:00" "800" "" "20" "7499" "-0.000025253223" "SALESMAN" "7698" "20-FEB-1981 AD 00:00:00" "1600" "30+ 0" "30" "7521" "WARD" "SALESMAN" "7698" "22-FEB-1981 AD 00:00:00" "1250" "500" "30" "7566" "JONES" "MANAGER" "7839" "02-APR-1981 AD 00:00:00" "2975" "" "20" "7654" "MARTIN" "SALESMAN" "7698" "28-SEP-1981 AD 00:00:00" "1250" "1400" "30" [ many more lines here ]
This looks familiar, use the above information and your knowledge of the emp table to compose:
UNLOAD TABLE emp ( empno number, ename char, job char, mgr number, hiredate date, sal number, comm number deptno number) STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530));
$ dul UnLoader: Version 2.0.0.0 - Very Restricted on Tue May 16 11:46:33 1995 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Loaded 350 segments Loaded 204 extents Extent map sorted DUL> UNLOAD TABLE emp ( empno number, ename char, job char, mgr number, DUL 2> hiredate date, sal number, comm number deptno number) DUL 3> STORAGE ( TABNO 0 EXTENTS( FILE 1 BLOCK 10530)); . unloading table EMP 14 rows unloaded DUL>quit
This can generate output similar to below. Normally this should not happen since you should create a demo database and check this via the DUL documented (in html page) query.
The mismatch in DBA’s is only in the file number (first number in brackets) part. The second number, the block number, is correct.
Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:40:33 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [4][2] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][3] DBA in block mismatch [4][3] DUL: Warning: Bad cache layer header file#=1, block#=3 ...........and etc..........
This may create output similar to below, but many other flavours are possible. In this case we are a fixed number of blocks off. The file number is correct. The difference in the block numbers is constant.:
Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:44:23 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [1][3] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][3] DBA in block mismatch [1][4] DUL: Warning: Bad cache layer header file#=1, block#=3 ...........and etc..........
This may generate output similar to the following:
Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:46:10 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. . unloading table OBJ$ DUL: Warning: file# 0 is out of range DUL: Warning: Cannot read data block file#=0, block# = 262145 OS error 2: No such file or directory DUL: Warning: file# 0 is out of range DUL: Warning: Cannot read data block file#=0, block# = 262146 OS error 2: No such file or directory ...........and etc..........
The following output was generated when the db_block_size was set too small. The correct value was 4096 and it was set to 2048. Normally, the value for this parameter should be taken from the Oracle instances’s init.ora file and will not be correctly set.
Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Thu Sep 4 12:38:25 1997 Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved. Session altered. Session altered. Session altered. Session altered. Session altered. DUL: Warning: Block[1][2] DBA in block mismatch [513][1159680] DUL: Warning: File=1, block 2: illegal block version 2 DUL: Warning: Block[1][2] Illegal block type[0] DUL: Warning: Bad cache layer header file#=1, block#=2 DUL: Warning: Block[1][4] DBA in block mismatch [1][2] DUL: Warning: File[1]Block[4]INCSEQ mismatch[90268!=0] DUL: Warning: Bad cache layer header file#=1, block#=4 DUL: Warning: Block[1][6] DBA in block mismatch [1][3] DUL: Warning: File[1]Block[6]INCSEQ mismatch[139591710!=86360346] DUL: Warning: Bad cache layer header file#=1, block#=6 ...........and etc..........
If you get the following error it is caused by the data dictionary tables “USER$, OBJ$, TAB$ and COL$” not being correctly generated. To fix this error simply delete all dictv6.ddl or dictv7.ddl created .dat and .ctl files and restart.
Data UnLoader: Release 3.2.0.1 - Internal Use Only - on Wed Sep 3 10:49:30 1997
Copyright (c) 1994/95 Oracle Corporation, The Netherlands. All rights reserved.
DUL: Error: Quote missing
If you do not know anything about the structure of a EXP dump file this can be difficult. Here is a quick explanation. Apart from the file header a dump file has MARKERS that identify the various sections. In each table section there will be SQL statements. The most interrsesting part is the create table statement, followed by the insert into table statement. The insert statement is directly followed by the bind information, (number of columns, and for each column its type and bind length and a small bit more). Then it is followed by the actual columns. Each column is preceded by a two byte length, followed by the actual column data. There are several tricks for longer columns possible. The end of the column data is marked by the special length marker OXFFFF. There is no marker for the beginning of a row. Resynching after a corruption is trial and error. Corruption are generally not immediate detectable. The format is slightly different for DIRECT export, so you will have to use the DIRECT option for DIRECT exports. The offset to be specified is the beginning of a row. In general the first one directly behind the bind array, but for optimal flexibility you can start anywhere in the row data.
The first step is to scan the dump file to find the offsets and the sql statements. Each output line starts with the offset where the item is found.
DUL> scan dump file expdat.dmp; 0: CSET: 1 (US7ASCII) # Character set info from the header 3: SEAL EXPORT:V10.02.01 # the Seal - the exp version tag 20: DBA SYSTEM # exp done as SYSTEM 8461: CONNECT SCOTT # section for user SCOTT 8475: TABLE "EMP" # complete create table staement 8487: CREATE TABLE "EMP" ("EMPNO" NUMBER(4, 0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4, 0), "HIREDATE" DATE, "SAL" NUMBER(7, 2), "COMM" NUMBER(7, 2), "DEPTNO" NUMBER(2, 0)) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "USERS" LOGGING NOCOMPRESS # Insert statement 8829: INSERT INTO "EMP" ("EMPNO", "ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM", "DEPTNO") VALUES (:1, :2, :3, :4, :5, :6, :7, :8) # BIND information 8957: BIND information for 8 columns col[ 1] type 2 max length 22 col[ 2] type 1 max length 10 cset 31 (WE8ISO8859P1) form 1 col[ 3] type 1 max length 9 cset 31 (WE8ISO8859P1) form 1 col[ 4] type 2 max length 22 col[ 5] type 12 max length 7 col[ 6] type 2 max length 22 col[ 7] type 2 max length 22 col[ 8] type 2 max length 22 Conventional export # Conventional means NOT DIRECT 9003: start of table data # Here begins the first row
Now build an unexp statement from the create table statement and the direct/conventional information and the start of the column data.
UNEXP TABLE "EMP" ("EMPNO" NUMBER(4, 0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4, 0), "HIREDATE" DATE, "SAL" NUMBER(7, 2), "COMM" NUMBER(7, 2), "DEPTNO" NUMBER(2, 0)) dump file expdat.dmp from 9003; Unloaded 14 rows, end of table marker at 9670 # so we have our famous 14 rows
This builds the normal SQL*Loader file and a matching control file. In the output file one extra column is added, this is related to the status of the row. A P means the row is Partial, (some columns missing) R means Resynch, it is the first row after a resynchronisation. O means Overlap, the previous row had errors, but the new row partly overlaps the other one.
Table Of Contents
~~~~~~~~~~~~~~~~~
1. Introduction
2. Using DUL
2.1 Create an appropriate init.dul file
2.2 Create the control.dul file
2.3 Unload the object information
2.4 Invoke DUL
2.5 Rebuild the database
3. How to rebuild object definitions that are stored in the data dictionary ?
4. How to unload data when the segment header block is corrupted ?
5. How to unload data when the file header block is corrupted ?
6. How to unload data without the system tablespace ?
7. Appendix A : Where to find the executables ?
8. References
1. Introduction
~~~~~~~~~~~~~~~
This document is to explain how to use DUL rather than to give a full
explanation of Bernard’s Data UnLoader capabilities.
This document is for internal use only and should not be given to customers at
any time, Dul should always be used by or under the supervision of a support
analyst.
DUL (Data UnLoader) is intended to retrieve data from the Oracle Database that
cannot be retrieved otherwise. This is not an alternative for the export
utility or SQL*Loader. The database may be corrupted but an individual data
block used must be 100% correct. During all unloading checks are made to make
sure that blocks are not corrupted and belong to the correct segment. If a
corrupted block is detected by DUL, an error message is printed in the loader
file and to the standard output, but this will not terminate the unloading of
the next row or block.
2. Using DUL
~~~~~~~~~~~~
First you must retrieve the necessary information about the objects that exists
in the database, these statistics will be loaded into the DUL dictionary to
unload the database objects.
This information is retrieved from the USER$, OBJ$, TAB$ and COL$ tables that
were created at database creation time, they can be unloaded based on the fact
that object numbers are fixed for these tables due to the rigid nature of sql.
bsq. DUL can find the information in the system tablespace, therefor the system
tablespace datafile(s) must be included in the control file, if this datafile(s)
is not present see chapter 6.
2.1 Create an appropriate “init.dul” file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
REM Platform specific parameters (NT)
REM A List of parameters for the most common platforms can be obtained from
REM
osd_big_endian_flag=false
osd_dba_file_bits=10
osd_c_struct_alignment=32
osd_file_leader_size=1
osd_word_size = 32
REM Sizes of dul dictionary caches. If one of these is too low startup will
REM fail.
dc_columns=2000000
dc_tables=10000
dc_objects=1000000
dc_users=400
dc_segments=100000
REM Location and filename of the control file, default value is control.dul
REM in the current directory
control_file = D:\Dul\control_orcl.dul
REM Database blocksize, can be found in the init
REM retrieved by doing “show parameter %db_block_size%” in server manager
REM (svrmgr23/30/l) changes this parameter to whatever the block size is of
REM the crashed database.
db_block_size=4096
REM Can/must be specified when data is needed into export/import format.
REM this will create a file suitable to use by the oracle import utility,
REM although the generated file is completely different from a table mode
REM export generated by the EXP utility. It is a single table dump file
REM with only a create table structure statement and the table data.
REM Grants, storage clauses, triggers are not included into this dump file !
export_mode=true
REM Compatible parameter must be specified an can be either 6, 7 or 8
compatible=8
REM This parameter is optional and can be specified on platforms that do
REM not support long file names (e.g. 8.3 DOS) or when the file format that
REM DUL uses “owner_name.table_name.ext” is not acceptable. The dump files
REM will be something like dump001.ext, dump002.ext, etc in this case.
file = dump
A complete list can be obtained at
html section “DUL Parameters” although this init.dul file will work in most
cases and contains all accurate parameters to succesfully complete the
unloading.
2.2 Create the “control.dul” file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A good knowledge about the logical tablespace and physical datafile
structure is needed or you can do the following queries when the database
is mounted :
Oracle 6, 7
———–
> connect internal
> spool control.DUL
> select * from v$dbfile;
> spool off
Oracle 8
——–
> connect internal
> spool control.DUL
> select ts#, rfile#, name from v$datafile;
> spool off
Edit the spool file and change, if needed, the datafile location and stripe
out unnecessary information like table headers, feedback line, etc…
A sample control file looks something like this :
REM Oracle7 control file
1 D:\DUL\DATAFILE\SYS1ORCL.DBF
3 D:\DUL\DATAFILE\DAT1ORCL.DBF
7 D:\DUL\DATAFILE\USR1ORCL.DBF
REM Oracle8 control file
0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF
1 2 D:\DUL\DATAFILE\USR1ORCL.DBF
1 3 D:\DUL\DATAFILE\USR2ORCL.DBF
2 4 D:\DUL\DATAFILE\DAT1ORCL.DBF
Note : Each entry can contain a part of a datafile, this can be useful when
you need to split datafiles that are too big for DUL, so that each
part is smaller than for example 2GB. For example :
REM Oracle8 with a datafile split into multiple parts, each part is
REM smaller than 1GB !
0 1 D:\DUL\DATAFILE\SYS1ORCL.DBF
1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1 endblock 1000000
1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 1000001 endblock 2000000
1 2 D:\DUL\DATAFILE\USR1ORCL.DBF startblock 2000001 endblock 2550000
2.3 Unload the object information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Start the DUL utility with the appropriate ddl (Dul Description Language)
script. There are 3 scripts available to unload the USER$, OBJ$, TAB$ and
COL$ tables according to the database version.
Oracle6 :> dul8.exe dictv6.ddl
Oracle7 :> dul8.exe dictv7.ddl
Oracle8 :> dul8.exe dictv8.ddl
Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Jun 22 22:19:
Copyright (c) 1994/1999 Bernard van Duijnen All rights reserved.
Parameter altered
Session altered.
Parameter altered
Session altered.
Parameter altered
Session altered.
Parameter altered
Session altered.
. unloading table OBJ$ 2271 rows unloaded
. unloading table TAB$ 245 rows unloaded
. unloading table COL$ 10489 rows unloaded
. unloading table USER$ 22 rows unloaded
. unloading table TABPART$ 0 rows unloaded
. unloading table IND$ 274 rows unloaded
. unloading table ICOL$ 514 rows unloaded
. unloading table LOB$ 13 rows unloaded
Life is DUL without it
This will unload the data of the USER$, OBJ$, TAB$ and COl$ data dictionary
tables into SQL*Loader files , this can not be manipulated into dump files
of the import format. The parameter export_mode = false is hardcoded into
the ddl scripts and can not be changed to the value “true” since this will
cause DUL to fail with the error:
. unloading table OBJ$
DUL: Error: Column “DATAOBJ#” actual size(2) greater than length in column
definition(1)
………….etc……………
2.4 Invoke DUL
~~~~~~~~~~~~~~
Start DUL in interactive mode or you can prepare a scripts that contains all
the ddl commands to unload the necessary data from the database. I will
describe in this document the most used commands, this is not a complete list
of possible parameters that can be specified. A complete list can be found at
section “DDL Description”.
DUL> unload database;
=> this will unload the entire database tables(includes sys’tables as well)
DUL> unload user
=> this will unload all the tables owned by that particullarly user.
DUL> unload table
=> this will unload the specified table owned by that username
DUL> describe
=> will represent the table columns with there relative pointers to the
datafile(s) owned by the specified user.
DUL> scan database;
=> Scans all blocks of all data files.
Two files are generated:
1: seg.dat information of found segment headers (index/cluster/table)
(object id, file number, and block number).
2: ext.dat information of contiguous table/cluster data blocks.
(object id(V7), file and block number of segment header (V6),
file number and block number of first block,
number of blocks, number of tables)
DUL> scan tables;
=> Uses seg.dat and ext.dat as input.
Scans all tables in all data segments (a header block and at least one
matching extent with at least 1 table).
2.5 Rebuild the database
~~~~~~~~~~~~~~~~~~~~~~~~
Create the new database and use import or SQL*Loader to restore the data
retrieved by DUL. Note that when you only unloaded the data that table
structures, indexation, grants, PL/SQL and triggers will no longer exist in
the new database. To obtain an exactly same copy of the database as before
you will need to rerun your creation scripts for the tables, indexes, PL/SQL,
etc.
If you don’t have these scripts then you will need to perform the steps
described in section 3 of this document.
3. How to rebuild object definitions that are stored in the data dictionary
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You want to rebuild PL/SQL(packages, procedures, functions or triggers), grants,
indexes, constraints or storage clauses(old table structure) with DUL. This can
be done but is a little bit tricky. You need to unload the relevant data
dictionary tables using DUL and then load these tables into a healthy database,
be sure to use a different user than sys or (system). Loading the data
dictionary tables of the crashed database into the healthy database dictionary
could corrupt the healthy database as well.
Detailed explanation to retrieve for example pl/sql packages / procedures /
functions from a corrupted database :
1) Follow the steps explained in the “Using DUL” section and unload the data
dictionary table “source$”
2) Create a new user into a healthy database and specify the desired default
and temporary tablespace.
3) Grant connect, resource, imp_full_database to the new user.
4) Import/load the table “source$” into the new created schema:
e.g.: imp80 userid=newuser/passw file=d:\dul\scott_emp.dmp
log=d:\dul\impemp.txt full=y
5) You can now query from the table
procedures/functions from the corrupted database. Scripts can be found on
WebIv to generate such PL/SQL creation scripts.
The same steps can be followed to recreate indexes, constraints, and storage
parameters or to regrant privileges to the appropiate users. Please notice that
you always need to use a script of some kind that can recreate the objects and
include all the features of the crashed database version. For example : when
the crashed database is of version 7.3.4 and you have several bitmap indexes,
if you would use a script that supports version 7.3.2 or prior, then you won’t
be able to recreate the bitmap indexes succesful !
4. How to unload data when the segment header block is corrupted
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When DUL can’t retrieve data block information on the normal way, it can scan
the database to create its own segment/extent map. The procedure of scanning
the database is necessary to unload the data from the datafiles.
(to illustrate this example I copied an empty block ontop of the segment header
block)
1) Create an appropiate “init.dul” (see 2.1) and “control.dul” (see 2.2) file.
2) Unload the table. This will fail and indicate that there is a corruption in
the segment header block:
DUL> unload table scott.emp;
. unloading table EMP
DUL: Warning: Block is never used, block type is zero
DUL: Error: While checking tablespace 6 file 10 block 2
DUL: Error: While processing block ts#=6, file#=10, block#=2
DUL: Error: Could not read/parse segment header
0 rows unloaded
3) run the scan database command :
DUL> scan database;
tablespace 0, data file 1: 10239 blocks scanned
tablespace 6, data file 10: 2559 blocks scanned
4) Indicate to DUL that it should use its own generated extent map rather than
the segment header information.
DUL> alter session set use_scanned_extent_map = true;
Parameter altered
Session altered.
DUL> unload table scott.emp;
. unloading table EMP 14 rows unloaded
5. How to unload data when the datafile header block is corrupted
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A corruption in the datafile header block is always listed at the moment you
open the database this is not like a header segment block corruption (see point
4) where the database can be succesfully openend and the corruption is listed
at the moment you do a query of a table. Dul has no problems with recovering
from such situations although there are other alternatives of recovering from
this situation like patching the datafile header block.
The error you will receive looks something like :
ORACLE instance started.
Total System Global Area 11739136 bytes
Fixed Size 49152 bytes
Variable Size 7421952 bytes
Database Buffers 4194304 bytes
Redo Buffers 73728 bytes
Database mounted.
ORA-01122: database file 10 failed verification check
ORA-01110: data file 10: ‘D:\DATA\TRGT\DATAFILES\JUR1TRGT.DBF’
ORA-01251: Unknown File Header Version read for file number 10
6. How to unload data without the system tablespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If datafiles are not available for the system tablespace the unload can still
continue but the object information can’t be retrieved from the data dictionary
tables USER$, OBJ$, TAB$ and COL$. So ownername, tablename and columnnames will
not be loaded into the DUL dictionary. Identifying the tables can be an
overwhelming task and a good knowledge of the RDBMS internals are needed here.
First of all you need a good knowledge of your application and it’s tables.
Column types can be guessed by DUL, but table and column names will be lost.
Any old system tablespace from the same database (may be weeks old) can be a
great help !
1) Create the “init.dul” file and the “control.dul” file as explained in above
steps 1 and 2. In this case the control file will contain all the datafiles
from which you want to restore but it doesn’t require the system tablespace
information.
2) Then You invoke dul and type the following command :
DUL> scan database;
data file 6 1280 blocks scanned
This will build the extent and segment map. Probably the dul command
interpreter will be terminated as well.
3) reinvoke the dul command interpreter and do the following :
Data UnLoader: Release 8.0.5.3.0 – Internal Use Only – on Tue Aug 03 13:33:
Copyright (c) 1994/1999 Oracle Corporation, The Netherlands. All rights res
Loaded 4 segments
Loaded 2 extents
Extent map sorted
DUL> alter session set use_scanned_extent_map = true;
DUL> scan tables; (or scan extents;)
Scanning tables with segment header
Oid 1078 fno 6 bno 2 table number 0
UNLOAD TABLE T_O1078 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN )
STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 2));
Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid%
1 4 2 0% 0% 0% 100% 100% 0% 0%
2 4 10 0% 100% 100% 100% 0% 0% 0%
3 4 8 0% 100% 100% 100% 0% 0% 50%
“10” “ACCOUNTING” “NEW YORK”
“20” “RESEARCH” “DALLAS”
“30” “SALES” “CHICAGO”
“40” “OPERATIONS” “BOSTON”
Oid 1080 fno 6 bno 12 table number 0
UNLOAD TABLE T_O1080 ( C1 NUMBER, C2 UNKNOWN, C3 UNKNOWN, C4 NUMBER,
C5 DATE, C6 NUMBER, C7 NUMBER, C8 NUMBER )
STORAGE ( TABNO 0 EXTENTS( FILE 6 BLOCK 12));
Colno Seen MaxIntSz Null% C75% C100 Num% NiNu% Dat% Rid%
1 14 3 0% 0% 0% 100% 100% 0% 0%
2 14 6 0% 100% 100% 100% 0% 0% 21%
3 14 9 0% 100% 100% 100% 0% 0% 0%
4 14 3 7% 0% 0% 100% 100% 0% 0%
5 14 7 0% 0% 0% 0% 0% 100% 0%
6 14 3 0% 0% 0% 100% 100% 0% 0%
7 14 2 71% 0% 0% 100% 100% 0% 0%
8 14 2 0% 0% 0% 100% 100% 0% 0%
“7369” “SMITH” “CLERK” “7902” “17-DEC-1980 AD 00:00:00” “800” “” “20”
“7499” “ALLEN” “SALESMAN” “7698” “20-FEB-1981 AD 00:00:00” “1600” “300” “30”
“7521” “WARD” “SALESMAN” “7698” “22-FEB-1981 AD 00:00:00” “1250” “500” “30”
“7566” “JONES” “MANAGER” “7839” “02-APR-1981 AD 00:00:00” “2975” “” “20”
“7654” “MARTIN” “SALESMAN” “7698” “28-SEP-1981 AD 00:00:00” “1250” “1400” “30”
Note : it might be best that you redirect the output to a logfile since
commands like the “scan tables” can produce a lot of output.
On Windows NT you can do the following command :
C:\> dul8 > c:\temp\scan_tables.txt
scan tables;
exit;
4) Identify the lost tables from the output of step 3; if you look carefully to
the output above then you will notice that the unload syntax is already given
but that the table name will be of the format t_0
names will be of the format C
the datatype as it was before.
Look especially for strings like “Oid 1078 fno 6 bno 2 table number 0” where:
oid = object id, will be used to unload the object
fno = (data)file number
bno = block number
5) Unload the identified tables with the “unload table” command :
DUL> unload table dept (deptno number(2), dname varchar2(14),
loc varchar2(13)) storage (OBJNO 1078)
Unloading extent(s) of table DEPT 4 rows.