YAOTU INSIGHTS

达梦DM8迁移实战:DTS从Oracle导数据全流程与避坑指南

达梦DM8迁移实战:DTS从Oracle导数据全流程与避坑指南
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端口的情况非常常见。达梦默认端口5236Oracle默认端口1521MySQL默认端口3306PostgreSQL默认端口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)精度和标度保持一致NUMBERNUMERIC未指定精度时达梦默认可能为NUMERIC(38)DATEDATEOracle的DATE包含时分秒达梦DATE也支持TIMESTAMP(p)TIMESTAMP(p)精度参数保留CLOBCLOB最大长度按达梦参数配置BLOBBLOB二进制大字段BINARY_FLOATFLOAT二进制的单精度浮点BINARY_DOUBLEDOUBLE双精度浮点RAW(n)VARBINARY(n)二进制定长数据ROWIDVARCHAR(18)工具自动转换不用手动处理在这个基础上DTS还提供了“类型映射”界面允许你手动修改某一张表、甚至某个字段的转换规则。界面里左侧是源库的表字段右侧是目标库的对应字段你可以直接改目标库的类型定义甚至可以改成VARCHAR2写法。为什么要强调这个界面因为达梦兼容Oracle模式建表语句里写VARCHAR2也是可以执行的但实际存储类型还是VARCHAR。如果你要保留Oracle的DDL风格可以在类型映射里不去动它但如果后续有跨库数据比对、代码生成之类的需求建议规规矩矩改成达梦的VARCHAR。4.2 主键、自增列与默认值的特殊处理字段类型映射不是表结构转换的全部主键、自增列、默认值这三个东西才是最容易出问题的。主键迁移DTS默认会把源库的主键约束一并迁移到目标库。这一步对于大多数表没有问题。但如果你源库的主键是复合主键并且其中一个字段是NUMBER类型到达梦变成NUMERIC相应的主键索引也会跟着变一般没问题。真正需要留意的是源库主键如果用了反向索引这就是Oracle的REVERSE关键字达梦不识别工具会默认降级为普通索引语义上能接受。自增列是异构迁移的重灾区。Oracle实现自增靠的是序列加触发器MySQL靠的是AUTO_INCREMENTSQL 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 USERIDSYSDBA/SYSDBAlocalhost:5236 FILE/data/backup/order.dmp \ SCHEMASORDER_SCHEMAdmimport是导入命令对应导出文件往里灌dmimport USERIDSYSDBA/SYSDBAlocalhost:5236 FILE/data/backup/order.dmp \ SCHEMASORDER_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等主流库迁到达梦的完整流程。刚开始用时别贪快把源库结构梳理清楚类型映射检查仔细字符集确认好性能参数测一轮基本上就能稳稳跑通。等用顺手了你会发现迁移这种活在工具辅助下真的可以从“让人崩溃的体力活”变成“按部就班的流水线作业”。