1. 从Oracle迁到达梦,第一课就是别再手工建表
国产化替代这两年,我经手最多的活就是从Oracle、MySQL往达梦DM8迁数据。一开始我还特别天真,想着手工在达梦里把表建好,再把源库数据导出成CSV导进去。头几个小表确实糊弄过去了,等遇到几十张带外键关联的业务表,光整理字段类型映射就能把人干崩溃,更别提主键、自增列、CLOB大字段这些细节,稍不注意数据就歪了。
DM8自带的DM数据迁移工具,解决的就是这个问题,它能把你从“手工拼DDL+搬数据”的体力活里解放出来,变成一条可视化的流水线。简单说,这个工具能做到三件事:
- 自动抓取源库的表结构,转换成达梦的建表语句
- 自动搬运数据,并做必要的类型转换
- 支持视图、序列、存储过程、函数等对象一起迁移
对于正在做信创替换、数据库异构迁移的团队,这个工具基本是必学的。接下来的内容,就按我从一个DM8新手到能独立完成整套迁移的路径来写,关键坑点都给你们标出来了。
2. 工具启动与环境准备:第一次打开DTS容易踩的坑
2.1 DTS从哪来,怎么启动
DM数据迁移工具的官方缩写是DTS,它不是单独安装的组件,而是随DM8数据库一起发布的图形化工具。Windows环境下,安装完DM8之后,在开始菜单里能找到“达梦数据迁移工具”,或者直接去DM安装目录下的tool文件夹找dts.exe。
Linux环境下就一句话,进安装目录的tool文件夹,执行./dts就行。这里有个前提,DTS依赖图形界面,纯命令行服务器需要先配好X11转发或者VNC这类远程桌面环境,否则起不来。我一开始在一台只有SSH的CentOS上死活起不来,后来才反应过来是这个原因。
2.2 首次启动容易遇到的三个小问题
第一次用DTS,我遇到过几个挺影响心情的问题,提前说一下能帮你少走弯路:
第一,JDK版本冲突。DTS本身是Java开发的,如果服务器上装有其他版本的JDK,环境变量指定的JAVA_HOME不对,可能出现界面起不来、启动白屏或者拖拽控件卡死的情况。解决办法很简单,确认JAVA_HOME指向DM8自带的JRE目录即可,DTS安装时会在tool目下带一个jre,直接用它。
第二,连接源库需要驱动。DTS对Oracle、MySQL这类数据库的连接,依赖官方JDBC驱动。达梦安装包内置了一部分驱动,但版本不一定匹配你源库的版本。我第一次迁Oracle 11g,用默认驱动直接报ORA-28040,后面换了个ojdbc8.jar才连上。驱动的放置位置一般在DTS安装目录的lib文件夹下,记得放进去之后重启DTS。
第三,端口和防火墙。图形界面上连接源库,建议先在命令行用telnet确认端口通不通,别一上来就在DTS里填连接信息。尤其是源库在远端云服务器时,安全组规则漏放3306/1521端口的情况非常常见。
- 达梦默认端口:5236
- Oracle默认端口:1521
- MySQL默认端口:3306
- PostgreSQL默认端口:5432
这一关过了,工具能正常打开、连得上源库和目标库,剩下的就是配置迁移任务了。
3. 创建迁移任务的完整链路:从一步步配置到跑通
3.1 新建工程与迁移任务
打开DTS之后,第一步是新建工程。工程相当于一个项目容器,一次迁移的所有配置、日志、报告都会归集到这个工程下面,方便后续追踪和复用。建议一个数据库迁移项目建一个工程,用项目名命名,别把多个迁移任务都揉在一起。
新建完工程,右键选择“新建迁移”。这一步DTS会弹出一个迁移向导,第一个选择是迁移方式。DTS支持数据迁移、数据比对、定时同步三类核心功能,第一次做全量迁移,选“数据迁移”就行。
3.2 源库连接配置:不同数据库的差异
选择源库类型这一步,DTS会列出它支持的数据源。常见的有Oracle、MySQL、SQL Server、PostgreSQL、DB2、Sybase,还支持文本文件和Excel。选好类型之后填连接参数,这里有几个细节值得注意:
Oracle连接比较特殊,除了主机名、端口、用户名、密码之外,还需要填服务名或者SID。很多人按MySQL的思维惯性直接填数据库名,连的时候报ORA-12505。我一般是填服务名,端口1521,连接测试通过了再往下走。
MySQL连接要注意驱动版本和时区参数。高版本的MySQL驱动对连接URL里的serverTimezone参数有限制,不填可能连不上。DTS里不一定能直接编辑URL,所以遇到时区报错,检查一下mysql-connector-java的版本,太老的驱动直接换掉。
PostgreSQL连接相对省心,填好地址端口库名用户密码基本就通了。但注意一个隐藏问题,DTS连接PostgreSQL时,如果源库的表分布在多个schema下,对象的归属要看清,别漏了业务schema下的表。我第一次迁PG库,默认只看到了public下的表,业务表在一个独立schema里,差点迁了个寂寞。
3.3 迁移对象选择:全选之前先想三件事
源库连上之后,DTS会列出源库的所有对象,包括表、视图、序列、函数、存储过程、包、同义词等。很多人的第一反应是全选,我劝你先想清楚三件事:
第一,视图和表一起迁,得靠工具自己排序。如果表的迁移顺序不对,外键约束还没建好,数据可能插不进去。DTS默认会分析对象依赖关系,自动排序,这个逻辑是可靠的,不需要手工调整顺序。但如果出现外键相关的报错,先检查主表数据是否完整,再检查约束的延迟检查设置。
第二,存储过程和包,迁移完必须逐个编译。DTS能把源库的存储过程代码抓过来,但它不等于能直接跑。Oracle写的存储过程,里面如果用了一些达梦不兼容的包或者函数,编译就报错。所以选择对象时可以选,但后续一定要花时间做代码兼容性改造,没有捷径。
第三,大表和小表的迁移策略。如果一个超大表在迁移过程中失败,DTS会记录失败原因并继续迁移其他表,不会因为你舍弃了某张表就中断整个任务。所以对象选择时不用太纠结,先把全量同步跑一遍,出了问题单独处理失败项就行。
3.4 迁移选项与执行:这里藏着性能的关键
对象选完之后,DTS会让配置迁移选项。到这里很多人就习惯性下一步了,其实这一屏参数对性能影响很大,我有一次1800万行的订单表,默认参数跑了一个半小时,后来调了几个选项,时间直接压到25分钟,差距非常明显。
关键参数有几个:
批大小(Batch Size),默认值一般不大,对大表来说建议调到几千甚至上万。批大小决定每次提交多少行数据,调大可以减少网络往返和提交开销,但也不是越大越好,太大容易让目标库产生严重的UNDO压力。
快速装载(Fast Load),这个选项我强烈建议开启。开启之后DTS会利用达梦的高速数据装载能力,插入速度明显快一个量级。但要注意,快速装载模式下,目标表上不能有活动的事务,迁移期间最好别让业务系统持续往里写数据。
迁移模式,分先建表再导数据和边建边导两种。默认情况下DTS会在目标库先创建表结构,然后启动数据拷贝。如果你的源表数量特别多,建议保留默认,避免数据还没开始导,目标库的锁冲突已经满天飞了。
大字段处理,DTS默认支持CLOB、BLOB这类大字段的迁移。但需要留意的是,快速装载模式下大字段的处理可能受限,如果出现了大字段相关的报错,可以把这个选项单独关闭,单独处理大表。
配置好这些选项,点击开始,DTS会进入执行页面,实时显示每个对象的迁移状态和日志。迁移完成之后,最好花几分钟看一下左下角的统计摘要,是否有失败的表。有失败的话,系统会生成错误日志,定位到具体表之后,单独“重新迁移”即可。
4. 表结构转换与类型映射:迁移中最容易翻车的环节
4.1 常用Oracle类型到达梦的映射规则
数据迁移工具对表结构转换的核心逻辑,是维护了一套源库类型到达梦类型的映射规则。Oracle迁到达梦比较省心,因为达梦高度兼容Oracle,很多类型可以直接对应。我整理一个常用映射表,方便你迁移时快速核对:
| Oracle类型 | 达梦DM8类型 | 注意事项 |
|---|---|---|
| VARCHAR2(n) | VARCHAR(n) | 长度按字符数保留,无需变化 |
| NUMBER(p,s) | NUMERIC(p,s) | 精度和标度保持一致 |
| NUMBER | NUMERIC | 未指定精度时,达梦默认可能为NUMERIC(38) |
| DATE | DATE | Oracle的DATE包含时分秒,达梦DATE也支持 |
| TIMESTAMP(p) | TIMESTAMP(p) | 精度参数保留 |
| CLOB | CLOB | 最大长度按达梦参数配置 |
| BLOB | BLOB | 二进制大字段 |
| BINARY_FLOAT | FLOAT | 二进制的单精度浮点 |
| BINARY_DOUBLE | DOUBLE | 双精度浮点 |
| RAW(n) | VARBINARY(n) | 二进制定长数据 |
| ROWID | VARCHAR(18) | 工具自动转换,不用手动处理 |
在这个基础上,DTS还提供了“类型映射”界面,允许你手动修改某一张表、甚至某个字段的转换规则。界面里左侧是源库的表字段,右侧是目标库的对应字段,你可以直接改目标库的类型定义,甚至可以改成VARCHAR2写法。
为什么要强调这个界面?因为达梦兼容Oracle模式,建表语句里写VARCHAR2也是可以执行的,但实际存储类型还是VARCHAR。如果你要保留Oracle的DDL风格,可以在类型映射里不去动它,但如果后续有跨库数据比对、代码生成之类的需求,建议规规矩矩改成达梦的VARCHAR。
4.2 主键、自增列与默认值的特殊处理
字段类型映射不是表结构转换的全部,主键、自增列、默认值这三个东西,才是最容易出问题的。
主键迁移,DTS默认会把源库的主键约束一并迁移到目标库。这一步对于大多数表没有问题。但如果你源库的主键是复合主键,并且其中一个字段是NUMBER类型,到达梦变成NUMERIC,相应的主键索引也会跟着变,一般没问题。真正需要留意的是,源库主键如果用了反向索引(这就是Oracle的REVERSE关键字),达梦不识别,工具会默认降级为普通索引,语义上能接受。
自增列是异构迁移的重灾区。Oracle实现自增靠的是序列加触发器,MySQL靠的是AUTO_INCREMENT,SQL Server靠IDENTITY。达梦呢,支持IDENTITY关键字,也支持序列。DTS对Oracle的迁移策略,一般会把Oracle的序列和触发器都抓过来,做成达梦的序列加触发器方案,所以Oracle迁移过程相对平滑。而MySQL的AUTO_INCREMENT列迁到达梦,会自动转换成IDENTITY(1,1)。这里有一个小坑,源表的自增列如果当前值已经到了100万,但IDENTITY定义从1开始,后续插入新数据时,主键冲突的风险就来了。迁移完成后建议手动执行:
ALTER TABLE T_ORDER ALTER COLUMN ID SET IDENTITY(1000001, 1);默认值的处理相对简单,DTS会把default子句带过来,但有些函数类默认值,比如Oracle的SYSDATE,到达梦之后通常没问题,因为达梦也支持SYSDATE。但如果源库默认值是某个自定义函数,目标库必须提前创建好这个函数,否则建表会直接报错。
4.3 一个实际案例:NUMBER类型把精度吃掉了
我实际迁移过一个财务系统的流水表,里面有个金额字段,源库定义是NUMBER(12, 2),看起来没毛病。迁移完成后做数据校验,发现有一批数据的金额变成了100000000(一亿整),实际应该是100000000.55。一开始我怀疑是数据丢失,后来排查下来发现是类型映射环节出了问题。
原因是DTS的默认映射规则里,NUMBER(12, 2)按理应该映射为NUMERIC(12, 2),但当时那个版本的DTS对不带标度信息的NUMBER字段的映射有歧义。某些行数据在源库里因为历史原因存成了科学计数法风格,导出过程中精度被丢掉了。最后解决问题的办法,不是去改数据,而是直接在类型映射界面把目标字段显式改成NUMERIC(18, 2),增加存储精度的冗余,重新迁移一遍就好了。
所以这里给所有做迁移的人一个建议:迁移前到类型映射界面,把金额类、数量类的NUMBER字段全部检查一遍,确保精度标度正确,别指望默认规则一定不出错。
5. 字符集、大字段与性能:决定迁移质量的三个隐藏开关
5.1 字符集匹配:乱码问题的源头在这里
字符串乱码是我见得的比较多的问题,而且往往不是表象上的“全部乱码”,而是部分中文乱码、部分正常,排查起来很费劲。原因在于源库和达梦的字符集不一致时,DTS需要做字符集转换,而转换是否成功,取决于工具对源库编码的识别是否准确。
先解释一下达梦这边:DM8安装数据库实例时,会让你选择字符集,常见的有UTF-8、GBK、GB18030。不同字符集有不同的存储行为,GBK一个汉字占两个字节,UTF-8一个汉字占三个字节。
源库这边情况更复杂:MySQL的character_set_database、Oracle的NLS_CHARACTERSET、SQL Server的collation,定义各不相同。DTS在连接源库时,会尝试从驱动侧获取源库的编码信息,然后自动完成转换。但某些情况下,这个自动识别是不准的。
比如我从一台PostgreSQL迁移数据到DM8时,DTS提示“本地编码:pg_gbk, 导入文件编码:pg_utf8”,翻译一下就是工具觉得源库是GBK编码,但文件实际是UTF-8,两边对不上,结果导入达梦里的中文全是问号。这个问题我在DTS的“迁移选项”里找了半天,最后才发现在连接配置界面有一个手动指定源库编码的下拉框,把它改成UTF-8之后问题解决。
所以迁移前的字符集检查很重要,记住一个原则:先确认源库实际编码,再确认达梦目标库编码,最后在DTS连接配置里指定正确编码,不要依赖自动识别。
5.2 CLOB/BLOB大字段迁移的注意点
业务系统里的合同附件、审批意见、日志详情,一般都会用CLOB或BLOB来存。DTS对大字段的迁移支持是有的,但有几个操作细节值得注意。
第一,大字段表在迁移时,建议单独跑,不要和几十张小表混在一个批任务里。大字段迁移持续时间长,如果DTS任务中途失败,重启整个任务会导致已经迁移完的表重复劳动,浪费大量时间。
第二,CLOB字段如果内容特别大,默认的批大小可能导致内存占用过高、甚至内存溢出。遇到这种情况,把批大小调小,比如降到500,大字段的表能相对稳定地迁移完成。
第三,迁移完成后一定要抽查几条大字段记录,判断内容是否完整。CLOB容易被截断的一个典型场景是源库字符串里含有特殊控制字符,转换过程中被工具做了一次编码翻转,导致数据库存储的内容与原值不同。抽查的方式很简单,取一条源库的全文,和目标库对比长度即可:
SELECT LENGTH(REMARK) FROM T_ORDER WHERE ID = 1001; -- 源库和目标库分别执行后对比LENGTH值如果长度不一致,说明大字段内容有丢失或异常。
5.3 大表迁移性能的实测调优
前面提到1800万行的订单表,默认参数跑了一个半小时,调整后压到25分钟,具体的调整项目分享给你参考:
- 批大小从默认的1000调到5000,带来接近30%的提升
- 开启快速装载,这个对性能提升贡献最大
- 关闭DTS的逐行日志输出,日志从INFO改成WARN
- 迁移期间目标库设置自动扩展表空间
但要提醒一句,达梦开启了快速装载之后,目标表的数据写入走的不是普通INSERT路径,而是在底层做了更高效的数据装载。这时如果目标表上有触发器,触发器可能不会被触发,相关数据业务逻辑需要迁移完成后手工处理一遍。所以不要无脑开,先判断目标表是否有关联触发器,再决定是否启用快速装载。
另外,并行度也是一个可调项。DTS支持单表内部的多线程并行读取,也支持多表并行迁移。并行度开得过高会导致源库服务器CPU飙升,影响业务系统正常运行。建议先从并行度2开始测,观察源库压力再慢慢往上加。
6. 从图形界面向命令行与定时任务的扩展
6.1 dmexport/dmimport:适合脚本化迁移的另一条路
DTS图形界面虽然直观,但在自动化和批处理场景下不够灵活。如果你要一次迁移几十个库,或者需要把迁移流程沉淀到持续集成里,那就要用到达梦自带的逻辑导出导入工具dmexport和dmimport了。
dmexport是达梦的逻辑导出工具,用法和Oracle的exp有点类似。一条最简单的导出命令:
dmexport USERID=SYSDBA/SYSDBA@localhost:5236 FILE=/data/backup/order.dmp \ SCHEMAS=ORDER_SCHEMAdmimport是导入命令,对应导出文件往里灌:
dmimport USERID=SYSDBA/SYSDBA@localhost:5236 FILE=/data/backup/order.dmp \ SCHEMAS=ORDER_SCHEMA这里有个概念要分清楚,dmexport/dmimport是达梦实例之间的逻辑搬迁,而DTS面向的是异构数据源。如果你想从Oracle迁到达梦,没法用dmexport直接导出Oracle的数据,还是要走DTS,或者先用其他工具把Oracle导成通用格式文件,再通过dmimport导入。对于达梦实例之间的快速同步,命令行工具比DTS更有优势,也更容易做自动化。
还有个配套工具dmfldr,是达梦的高速数据装载命令,支持把文本格式的数据文件快速加载到表中。如果你有一部分历史数据已经导成了CSV或文本,就可以用cmd格式的dmfldr快速灌入。加载大文本文件时,它的性能比DTS图形界面默认的INSERT方式好不少。
6.2 DTS定时同步:切换窗口期的过渡利器
迁移项目里经常有这样一个阶段:核心业务数据需要从Oracle持续同步到达梦一段时间,验证达梦侧的稳定性之后才切换流量。这种场景DTS的定时同步功能就可以派上用场。
DTS的定时同步不是物理层面的数据复制,而是按期轮询源库的新增和变更数据,再同步到目标库。具体原理比较简单,定期按主键或时间戳拉取源库变化的数据,插入或更新到目标表。配置好在新建迁移时选择“定时同步”,然后设置轮询时间间隔,比如每30秒轮询一次。
但这里面有一个限制,定时同步对源库的表有要求,必须有主键或唯一索引,否则无法准确判断增量与更新。同时,源库如果做了物理删除操作,定时同步不一定能感知到,需要配合其他机制处理删除场景。所以定时同步更适合作为切换期过渡方案,不建议作为长期的生产级数据同步方案。生产级同步还是要考虑达梦的数据复制软件或者基于日志的同步工具。
6.3 DTS数据比对:迁移完别急着验收
迁移完成不等于数据正确,每次迁移完之后我都会用DTS的数据比对功能做一次校验。新建比对任务,选源库和目标库对应的表,工具就会自动对比两边的行数、主键值、关键字段内容,输出差异报告。
对于数据量大的表,数据比对默认是全表扫描,时间会比较长。我一般在比对任务里限定部分核心字段,比如金额、状态、时间字段,这些字段对业务正确性影响最大,优先比对它们。全字段比对可以放到深夜跑一次,作为最终验收依据。
还有一个更通用的校验思路,迁移完成后在源库和目标库各执行一次汇总SQL,对比汇总值。比如订单表:
SELECT COUNT(*) AS CNT, SUM(AMOUNT) AS TOTAL_AMOUNT FROM T_ORDER;两边结果一致,迁移才算基本稳了。如果数据量差异明显,优先用DTS的比对报告定位到具体表,再考虑是重跑迁移还是手工补数据。
数据校验通过之后,还要做一遍应用层面的联通测试,用业务的几个典型查询跑一遍,确认达梦的查询结果和源库一致。毕竟表结构对了、数据对了,SQL兼容性不对,业务照样跑不起来。这一步别省,尤其是存储过程、视图、函数这些对象,迁移之后的编译和回归测试更是不能漏。
整体来看,DTS这套工具链足够支撑从Oracle/MySQL等主流库迁到达梦的完整流程。刚开始用时别贪快,把源库结构梳理清楚,类型映射检查仔细,字符集确认好,性能参数测一轮,基本上就能稳稳跑通。等用顺手了,你会发现迁移这种活,在工具辅助下,真的可以从“让人崩溃的体力活”变成“按部就班的流水线作业”。