dul 11的研究

来源:这里教程网 时间:2026-03-03 20:59:26 作者:

dul 11的研究

* dul的名气比较大,做oracle恢复的人都知道这个工具,但是这个工具是国外的开发的,发布的版本一般人也是下载不到的,类似这类的工具有很多,国内常见的有odu、aul、prmdul等。

* 最早的时候我是用过9和10的版本,当时恢复的是单纯的堆表,没有大字段的数据,导出的时候有两种选择,第一是csv,第二是dmp格式,但是我发现一个问题是如果用户的表较多,就会产生多个dmp出来,那么再加上恢复数据就变得更加复杂,曾经我用它在windows环境下恢复过几千个表,当时写的是windows的批处理脚本。过了几年,现在大部分都是11g~19c的环境,再用这个版本就不太合适。

* 关于该工具的使用方法网上有很多,我这里不做太多的介绍,主要讲一下它的弊端吧,对中文的clob支持不太友好,导出的是二进制的unicode编码,但是导进去是乱码,目前我还没解决,有相关经验的可以帮我解解惑。

* 关于该工具的使用特别要注意的是不同的版本都有时间的限制,如果想用对应的版本就要修改软件发布的对应的时间,另外还要修改文件的创建时间。这块在windows上比较麻烦,linux上很好处理,下面文章我有介绍。

* 下面正式进入实验:

一、环境说明

1、1 环境

[oracle@his dul]$ ./dul11205 Data UnLoader: 11.2.0.5.0 - Internal Only - on Mon May 1 00:25:22 2017 with 64-bit io functions and the decompression option Copyright (c) 1994 2017 Bernard van Duijnen All rights reserved. Strictly Oracle Internal Use Only

Cannot start now You need a more recent DUL version for this os    --这里可以看到必须使用最近的dul,怎么解决呢?观察上面的Copyright (c) 1994 2017 Bernard van Duijnen All rights reserved. 只需要把操作系统时间改为2017年的,然后数据文件也改到那个时间。

再次打开dul就可以了

二、测试过程

2.1 配置dul说明

* 用过dul类似的工具都知道,dul的配置分为2个文件,一个是init.dul文件,另外一个是数据库的路径结构信息的文件control.dul(可自定义,按照init.dul配置的修改)。

2.2 配置init.dul

vi init.dul OSD_BIG_ENDIAN_FLAG=FALSE    --大端还是小端 osd_dba_file_bits=10 osd_c_struct_alignment=32 osd_file_leader_size=1 OSD_WORD_SIZE=32 dc_columns=2000000 dc_tables=100000 dc_objects=100000 dc_users=8000 dc_segments=1000000 db_block_size=8192            --数据块尺寸 control_file=/dul/control.dul    --控制文件的位置 export_mode=true    --导出成dmp #export_mode=false    --导出成csv,即sqlldr加载的文件 compatible=10             --兼容性参数,是什么版本就改成什么 buffer=200000000 #FILE_SIZE_IN_MB=1000 file=zlhis

2.3 配置control.dul

set heading off verify off trimspool on tab off echo off feedback off set trimout on set space 1 pagesize 0 linesize 999 set numwidth 3 select ts# || ' '|| rfile# || ' '|| name || ' block_size '|| block_size from v$datafile; vi control.dul

2.4 初始化数据库字典信息

初始化后,在/dul目录下生成的文件信息

[oracle@his dul]$ ll total 15448 -rw-r--r-- 1 oracle oinstall 752 May 1 00:09 ATTRIBUTE.ctl    --属性 -rw-r--r-- 1 oracle oinstall 1192966 May 1 00:09 ATTRIBUTE.dat -rw-r--r-- 1 oracle oinstall 332 May 1 00:09 BOOTSTRAP.ctl    --引导 -rw-r--r-- 1 oracle oinstall 18907 May 1 00:09 BOOTSTRAP.dat -rw-r--r-- 1 oracle oinstall 950 May 1 00:09 COL.ctl            --列 -rw-r--r-- 1 oracle oinstall 6627420 May 1 00:09 COL.dat -rw-r--r-- 1 oracle oinstall 754 May 1 00:09 COLLECTION.ctl -rw-r--r-- 1 oracle oinstall 127466 May 1 00:09 COLLECTION.dat -rw-r--r-- 1 oracle oinstall 608 May 1 00:09 COLTYPE.ctl -rw-r--r-- 1 oracle oinstall 162407 May 1 00:09 COLTYPE.dat -rw-r--r-- 1 oracle oinstall 392 May 1 00:09 ICOL.ctl -rw-r--r-- 1 oracle oinstall 175558 May 1 00:09 ICOL.dat -rw-r--r-- 1 oracle oinstall 810 May 1 00:09 IND.ctl            --索引的控制文件 -rw-r--r-- 1 oracle oinstall 288360 May 1 00:09 IND.dat    --索引的数据文件 -rw-r--r-- 1 oracle oinstall 334 May 1 00:09 INDCOMPART.ctl -rw-r--r-- 1 oracle oinstall 0 May 1 00:09 INDCOMPART.dat -rw-r--r-- 1 oracle oinstall 678 May 1 00:09 INDPART.ctl -rw-r--r-- 1 oracle oinstall 5563 May 1 00:09 INDPART.dat -rw-r--r-- 1 oracle oinstall 684 May 1 00:09 INDSUBPART.ctl -rw-r--r-- 1 oracle oinstall 0 May 1 00:09 INDSUBPART.dat -rw-r--r-- 1 oracle oinstall 880 May 1 00:09 LOB.ctl        --lob相关信息 -rw-r--r-- 1 oracle oinstall 66978 May 1 00:09 LOB.dat -rw-r--r-- 1 oracle oinstall 336 May 1 00:09 LOBCOMPPART.ctl -rw-r--r-- 1 oracle oinstall 0 May 1 00:09 LOBCOMPPART.dat -rw-r--r-- 1 oracle oinstall 608 May 1 00:09 LOBFRAG.ctl -rw-r--r-- 1 oracle oinstall 40 May 1 00:09 LOBFRAG.dat -rw-r--r-- 1 oracle oinstall 600 May 1 00:09 OBJ.ctl        --对象 -rw-r--r-- 1 oracle oinstall 4720362 May 1 00:09 OBJ.dat -rw-r--r-- 1 oracle oinstall 254 May 1 00:09 PROPS.ctl    --数据库字符集等信息 -rw-r--r-- 1 oracle oinstall 1108 May 1 00:09 PROPS.dat -rw-r--r-- 1 oracle oinstall 880 May 1 00:09 TAB.ctl        --表 -rw-r--r-- 1 oracle oinstall 238130 May 1 00:09 TAB.dat -rw-r--r-- 1 oracle oinstall 334 May 1 00:09 TABCOMPART.ctl    --表分区相关 -rw-r--r-- 1 oracle oinstall 19 May 1 00:09 TABCOMPART.dat -rw-r--r-- 1 oracle oinstall 678 May 1 00:09 TABPART.ctl -rw-r--r-- 1 oracle oinstall 4498 May 1 00:09 TABPART.dat -rw-r--r-- 1 oracle oinstall 684 May 1 00:09 TABSUBPART.ctl -rw-r--r-- 1 oracle oinstall 1431 May 1 00:09 TABSUBPART.dat -rw-r--r-- 1 oracle oinstall 318 May 1 00:09 TS.ctl            --表空间 -rw-r--r-- 1 oracle oinstall 729 May 1 00:09 TS.dat -rw-r--r-- 1 oracle oinstall 392 May 1 00:09 TYPE.ctl        --type -rw-r--r-- 1 oracle oinstall 233062 May 1 00:09 TYPE.dat -rw-r--r-- 1 oracle oinstall 532 May 1 00:09 UNDO.ctl    --undo段 -rw-r--r-- 1 oracle oinstall 9721 May 1 00:09 UNDO.dat     -rw-r--r-- 1 oracle oinstall 252 May 1 00:09 USER.ctl        --用户表 -rw-r--r-- 1 oracle oinstall 1778 May 1 00:09 USER.dat -rwxrwxr-x 1 oracle oinstall 1904 Apr 1 2019 control.dul -rw-r--r-- 1 oracle oinstall 6429 May 1 00:09 dict.ddl    --数据字典 -rw-r--r-- 1 oracle oinstall 20163 May 1 00:09 dul.log    --dul允许过程中的日志 -rwxrwxr-x 1 oracle oinstall 851656 Apr 1 2019 dul11205 -rwxrwxr-x 1 oracle oinstall 901896 Apr 1 2019 dul12.2 -rwxrwxr-x 1 oracle oinstall 383 May 1 00:03 init.dul

----dul允许过程中的日志这个文件是很重要的,它记录了dul启动后参数的配置情况和对应的版本里面的参数,如果不清楚对应版本的参数,从中可以找到。

----USERS.dat可以了解到改库的schema信息,可以为unload user做参考。

2.5 按表导出测试

--从上面可以看到,dul在linux下对中文的表单独导出支持不太友好,不知道是不是字符集环境设置得不对,我改了NLS_LANG\LANG都不行。

--导出英文表是可以得,导出完成后会在库下按照表名生成对应的dmp文件。

2.6 按库导出测试

DUL> unload user zlhis;

--上面可以看到表很多都是中文的,但是导出后去/dul目录,没有一张中文的表;

--为了解决这个中文的问题,我调整了参数:

--删除/dul目录下的.dmp文件,再次 unload user zlhis;

--以上数据导出后,在导入的时候怎么弄,肯定不能单个文件去导入吧,所以我又写了脚本...

三、导入结果

3.1 准备相同版本的数据库,新建表空间、新建用户。

这一步简单,大家都会,跳过。

3.2 脚本

##方法1## function read_dir(){ read -t 30 -p "输入路径: " d read -t 30 -p "输入用户: " u read -t 30 -p "输入用户密码: " p rm /tmp/imp.sh &>/dev/null for file in `ls $d/*.dmp` do #echo 正在执行---------file=$file 的$u导入------------------ echo imp $u/$p file=$file log=$file"."log full=y feedback=10000 buffer=10240000 commit=y ignore=y >>/tmp/imp.sh done } daoru() { i=0; cat /tmp/imp.sh|while read line do if [ "$line" != "" ] && [ $i -lt 10 ];then $line & let i++; processnum=`ps -ef|grep imp|grep -v grep|wc -l` if [ $processnum -eq 10 ];then wait fi elif [ "$line" != "" ] && [ $i -lt 20 ];then $line & let i++; processnum=`ps -ef|grep imp|grep -v grep|wc -l` if [ $processnum -eq 10 ];then wait fi else $line & processnum=`ps -ef|grep imp|grep -v grep|wc -l` if [ $processnum -eq 10 ];then wait fi fi done wait } read_dir daoru

##方法2## #!/bin/bash start_time=$(date +"%Y-%m-%d %H:%M:%S") echo "Script started at $start_time" USER="zlhis" PASSWORD="his" DUMP_DIR="/dul/dump1" LOG_DIR="/dul/dump1" FAILED_TASKS="$LOG_DIR/failed_tasks.txt" MAX_CONCURRENT=100 #要小于数据库允许的并发,否则要提前修改 alter system set processes=1000 scope=spfile; mkdir -p "$LOG_DIR" > "$FAILED_TASKS" pids=() # 用于存储后台任务的 PID 列表 for dumpfile in "$DUMP_DIR"/*.dmp; do dumpname=$(basename "$dumpfile" .dmp) logfile="$LOG_DIR/$dumpname.log" echo "开始导入: $dumpfile -> $logfile" # 启动任务并将 PID 存储到数组中 ( imp userid=$USER/$PASSWORD file="$dumpfile" log="$logfile" full=y feedback=10000 buffer=10240000 commit=y ignore=y &>/dev/null if [ $? -ne 0 ]; then echo "$dumpfile" >> "$FAILED_TASKS" fi ) & pids+=($!) # 将后台任务 PID 添加到数组 # 检查并发数 while [ "${# pids[ @ ]}" -ge "$MAX_CONCURRENT" ]; do for i in "${! pids[ @ ]}"; do if ! kill "${ pids[i  ]}" 2>/dev/null; then unset pids[i  ] # 移除已完成的任务 fi done pids=("${pids[ @ ]}") # 重建数组(移除空值) sleep 1 # 等待片刻后再检查 done done # 等待所有剩余任务完成 for pid in "${ pids[ @ ]}"; do wait "$pid" done if [ -s "$FAILED_TASKS" ]; then echo "以下任务导入失败,请检查日志:" cat "$FAILED_TASKS" else echo "所有任务成功完成!" fi end_time=$(date +"%Y-%m-%d %H:%M:%S") echo "Script ended at $end_time" ps -ef|grep dmp|wc -l [oracle@his dump]$ ll *.dmp |wc -l 1045 [oracle@his dump]$ ll *.log|wc -l 1045 检查日志: find ./ -name "*.log" |xargs grep -A 2 'importing table'|more

3.23 脚本导入

--导入过程中另外的窗口也可以打开观察进程和日志情况

--表已经进来。

如果有报错,可以看对对应的日志;

或者看dmp导入过程中的日志;

find ./ -name "*.log" |xargs grep -A 2 'importing table'|more

四、clob测试导出导入

1、创建带有CLOB字段的表: sqlplus zlhis/his CREATE TABLE clob_test ( id NUMBER, clob_column CLOB ); 2、插入数据 INSERT INTO clob_test (id, clob_column) VALUES (1, TO_CLOB('这是一个CLOB字段的文本数据,啊发吉萨的房间里撒地方阿斯蒂芬')); alter system flush buffer_cache; 3、查询数据 SELECT id, clob_column FROM zlhis.clob_test; 4、编写vi init.dul OSD_BIG_ENDIAN_FLAG=FALSE osd_dba_file_bits=10 osd_c_struct_alignment=32 osd_file_leader_size=1 OSD_WORD_SIZE=32 dc_columns=20000000 dc_tables=10000000 dc_objects=10000000 dc_users=8000 dc_segments=10000000 db_block_size=8192 control_file=/dul/control.dul export_mode=true #export_mode=false compatible=11 buffer=2000000000 #FILE_SIZE_IN_MB=1000 file=zlhis #LDR_OUTPUT_IN_UTF8=TRUE 5、dmp导出测试 show datafiles; bootstrap; scan database; DUL> desc zlhis.clob_test; Table ZLHIS.CLOB_TEST obj#= 97187, dataobj#= 97191, ts#= 4, file#= 4, block#=301946 tab#= 0, segcols= 2, clucols= 0 Column information: icol# 01 segcol# 01 ID len 22 type 2 NUMBER(0) icol# 02 segcol# 02 CLOB_COLUMN len 4000 type 112 CLOB cs 852(ZHS16GBK) LOB Segment: dataobj#= 97188, ts#= 4, file#= 4, block#=318850 chunk=1 LOB Index: dataobj#= 97189, ts#= 4, file#= 4, block#=318858 unload table zlhis.clob_test; exit;

6、dmp导入测试 sqlplus zlhis/his truncate table clob_test; imp zlhis/his file=/dul/ZLHIS_CLOB_TEST.dmp log=/dul/ZLHIS_CLOB_TEST.log full=y feedback=10000 buffer=10240000 commit=y ignore=y SELECT id, clob_column FROM clob_test; [oracle@his dul]$ env|grep -i lang NLS_LANG=american_america.ZHS16GBK LANG=zh_CN.UTF-8 zh_CN zh_CN.gb18030 zh_CN.gb2312 zh_CN.gbk zh_CN.utf8 export.gbk 7、sqlldr导出测试 修改init.dul

export_mode=false

sqlldr zlhis/his control=ZLHIS_CLOB_TEST.ctl

再次导入,还是乱码。网上搜索了下,看了两篇文章,还是没能解决这个问题

--https://tool.ip138.com/ascii/ --http://www.killdb.com/2014/09/14/%e5%a6%82%e4%bd%95%e8%a7%a3%e5%86%b3oracle-dul%e6%81%a2%e5%a4%8dclob%e6%97%b6%e4%b8%ad%e6%96%87%e4%b9%b1%e7%a0%81%e9%97%ae%e9%a2%98%ef%bc%9f/

[oracle@his dul]$ iconv -l|grep UCS

10646-1:1993/UCS4/ CSUCS4// ISO-10646-UCS-2// ISO-10646/UCS2/ ISO-10646/UCS4/ UCS-2// UCS-2BE// UCS-2LE// UCS-4// UCS-4BE// UCS-4LE// UCS2// UCS4// [oracle@his dul]$ iconv -l|grep GB CN-GB// CSGB2312// CSISO58GB1988// EBCDIC-CP-GB// GB// GB2312// GB13000// GB18030// GBK// GB_1988-80// GB_198880// ISO646-GB// iconv -f UCS-4LE -t gb2312 ZLHIS_CLOB_TEST.dat > 1

cat 1

看了上面链接的文章,分析了数据,是unicode编码,用的"分割每列,空格一列后又是下一个字段,最后一个字段后是回车。通过iconv -f UCS-4LE -t gb2312 ZLHIS_CLOB_TEST.dat > 1还是不行。

五、总结

1、单表导出,测试中文不支持,要改为使用用户;unload 全库会遇到 DUL: FATAL Error: UTF16 can only be unloaded if LDR_OUTPUT_IN_UTF8=TRUE

2、lob字段对中文支持不友好,可能是外国佬写的原因吧。

3、init.dul里面的最重要的几个参数要清楚,特别是不同版本的数据库这里要修改,不然bootstrap生成的内容不准确,数据就无法导出。

4、dul类似的工具是最后一步,通过上面的操作也能看到这仅仅是把数据导出来,然后恢复,其实还有约束、索引、触发器、函数等等工作需要做,这也就要求必须要有应用厂商的人配合恢复,或者要有一个对应版本的测试库环境。

写到最后,提醒各位做好备份,技术再高,也怕挨刀。

相关推荐