摘要:这篇文章记录两组实验:一组用 dexp/dimp 把对象和数据从一个模式迁到另一个模式,一组用 dmfldr 装载 10004 行数据文件。重点不在命令本身,而在迁完之后怎么核对——对象有没有迁全、行数是否一致、中文有没有截断、错误行去了哪里、空值口径是否与预期一致。文中行数、错误码和日志结论都来自实际执行结果。
关键词:DM8;数据迁移;dexp/dimp;dmfldr;数据核对;BADFILE
一、三个工具各管什么
DM 里做数据迁移,常用的是 DTS、dexp/dimp 和 dmfldr,它们解决的问题不一样。DTS 是图形化工具,以对象为单位迁移,表、视图、序列、存储过程都能带过去,自带迁移评估和类型映射;dexp/dimp 是命令行下的逻辑导出导入工具,适合写进脚本、与备份配合;dmfldr 面向格式化平文件的高速装载,核心是数据文件、控制文件、日志和错误文件四样东西。
如果任务还包括持续增量同步或复杂的数据交换,那是 DMHS、DMETL 的范围,不要让这三个工具去承担。
图1 按数据形态选择迁移与同步工具(原创示意)
二、迁移前先记基线
不管用哪个工具,动手前先留两份底:源端对象清单和数据行数口径。这次实验的记录如下:
表1 迁移基线记录
项目 实际记录
目标端 单机 DM8(dminit 版本 03134284552-20260414-322369-20221),实例 DMSERVER,端口 5236
实例关键参数 页大小 8K,簇大小 16,大小写敏感 Y,字符集 UTF-8
目标规划 表空间 MIG_TS,用户 MIG_TEST(默认表空间 MIG_TS)
迁移范围 1 张表 FLDR_TEST(ID INT,NAME VARCHAR(50)),数据文件 10004 逻辑行
验证口径 源逻辑行数=成功行数+拒绝行数+跳过行数;空值与字符串分别核对
说明: 这次环境是单机 DM8,手上没有 Oracle 源库。为了把流程走完整,源端数据用同一实例里的 MIG_TEST 模式模拟,对象迁移用 dexp/dimp 的 REMAP_SCHEMA 完成;DTS 部分按官方文档保留为操作步骤。真正从 Oracle 迁过来时,下文的核对方法同样适用,差别只在源端连接和驱动配置。
对象按类型统计、名称单独导出留档:
SELECT OBJECT_TYPE, COUNT()
FROM ALL_OBJECTS
WHERE OWNER = 'MIG_TEST'
GROUP BY OBJECT_TYPE
ORDER BY 1;
注意: 不要拿统计信息里的 NUM_ROWS 当验收行数。统计信息可能没更新,关键表用 SELECT COUNT() 查,或用双方认可的口径复验。
三、dexp/dimp:脚本化迁移
图3 装载后行数与空值口径核对(真实实验截图)
终端显示“装载成功”不代表空值处理正确。NULL_MODE 要在控制文件或命令行里显式确定,装完用 IS NULL 和普通字符串各查一次。
五、踩坑记录
坑点 1:对象数量不少,却迁到了错误的用户或表空间
根因: 目标端没有提前规划用户、默认表空间和模式映射,迁移时沿用了默认目标。
处理: 迁移前把目标用户和默认表空间定好。这次先建 MIG_TS 表空间和 MIG_TEST 用户再迁移,核对时用 DBA_TABLES 确认所有者与表空间;dexp/dimp 路径用 REMAP_SCHEMA 显式指定目标模式。
坑点 2:中文被截断,标识符大小写异常
根因: 建实例时没评估字符集、字符长度和大小写敏感规则,这几项建完无法直接修改。
处理: 先用带中文、长字符串、混合大小写标识符的小样本试。这次数据文件全含中文,装载后 LENGTH(NAME) 与源文件一致,没有截断;60 字符超长行被正确拒绝并记入错误日志,说明字段长度约束在装载环节真实生效。
坑点 3:约束名称不同,被误判为对象丢失
根因: 源库和目标库都可能自动生成约束名。官方 DTS 文档说明,这类对象可能名称不同但功能相同。
处理: 对自动命名的对象比较定义、字段、约束类型和功能,不要求系统生成的名称完全一致。
坑点 4:dmfldr 报“参数分析出错”,引号被 shell 剥掉了(这次真实遇到)
现象: 按 ./dmfldr help 的说明书写命令:
./dmfldr SYSDBA/@localhost:5236 CONTROL='t2.ctl'
程序没有读控制文件,直接报错:
initialize fail.
参数分析出错[t2]
把控制文件换成绝对路径,报错变成“参数分析出错[/]”——报错里始终是参数值的第一个片段。
根因: 当前版本的 dmfldr 要求字符串参数的引号保留在参数值内部。写 CONTROL='t2.ctl' 时,shell 先剥掉单引号,dmfldr 实际收到 CONTROL=t2.ctl,解析失败。
处理: 把引号包进参数值再传给程序:
./dmfldr SYSDBA/@localhost:5236 "CONTROL='t2.ctl'"
改完立即正常解析并完成装载。“帮助文档示例在脚本里跑不通”这类问题,卡在 shell 引号处理和程序参数解析的交界上,排查时先想办法看程序实际收到了什么参数,不要一直在数据文件上找原因。
图4 参数引号被剥掉时的报错现场(真实实验截图)
坑点 5:终端显示完成,错误行却写到了别处(这次真实遇到)
现象: 第一次装载没显式指定 BADFILE,终端显示 load success 和错误统计,但计划目录 /dmdata/load 下找不到 BADFILE。错误行实际写到了工具默认路径 /home/dmdba/dmdbs/log/fldr.bad。
排查: 把 LOG 和 BADFILE 对照着看。BADFILE 里完整记录了 3 条拒绝行(缺列行 10002、类型错误行 abc、超长行 10001),与终端统计一致。
处理: LOG 和 BADFILE 一律显式指到规划目录;验收时核对“源逻辑行数=成功+拒绝+跳过”的关系。这次结果是 10004=10001+3+0(另有 1 行格式丢弃单独说明)。
图5 BADFILE 与 LOG 中记录的拒绝行及错误码(真实实验截图)
坑点 6:字符串 NULL 和数据库空值当成了一回事(这次真实遇到)
根因: NULL_MODE 决定文本里的 NULL 怎么解释:缺省 FALSE 按普通字符串装,设 TRUE 才按数据库空值处理。
处理: 在命令行或控制文件里明确口径,装完用 WHERE NAME IS NULL 和普通字符串查询各查一次(结果见表 2)。两种口径下 IS NULL 计数分别是 0 和 1,只看终端那句“装载成功”发现不了。
六、验收清单
图6 迁移完成后的验证环节(原创示意)
迁移最后一步是逐项核对,这次留下的证据:
表3 迁移验收清单
验证维度 核对方法 实际结果
对象清单 DBA_TABLES 查所有者与表空间 两侧模式均含 FLDR_TEST,表空间 MIG_TS
表行数 同一口径 SELECT COUNT(*) MIG_TEST 10001 = MIG_TEST2 10001
内容抽检 中文、超长、类型错误、空值样本 中文无截断;异常行进 BADFILE;空值口径一致
失败与拒绝行 检查 dmfldr LOG 与 BADFILE 3 拒绝+1 格式丢弃,错误码可复现
程序对象 检查视图、函数、存储过程是否可用 本次范围仅含表;含程序对象时应逐个编译验证
迁移后保护 验证通过后执行全量备份 应纳入例行计划,不能省略
七、小结
迁移工具把对象搬运和平文件装载做成了可配置、可追踪的过程,但迁移质量最终看留下的证据:迁之前的对象和行数基线,执行中的参数和日志,迁完之后的行数和内容核对。这次实验里,参数引号、BADFILE 默认位置、空值口径三个问题都属于“终端不报错、结果不正确”的类型。把 LOG、BADFILE 和 SQL 核对变成固定动作,“任务成功”才算真的成功。
参考资料
[1] 达梦技术文档:《DM 数据迁移工具》。
[2] 达梦技术社区:《dmfldr 快速装载工具》;具体参数以当前版本 ./dmfldr help 和使用手册为准。
