
上周刚帮客户把一个跑了快八年的Oracle系统迁到达梦DM8光表就有两千多张还有一堆视图、序列、存储过程。最开始想简单了让开发按表导出CSV再手工写程序导入结果连字段类型都调不过来更别提那些带CLOB大字段的表导一次崩一次。后来老老实实打开达梦自带的DTS数据迁移工具大部分工作其实就是图形界面里把任务配置清楚真正纠结的反而是迁移前的决策字符集怎么定、大小写敏感怎么设、约束要不要先迁、序列要不要对齐。今天把这些东西整理出来尤其是DTS的实操配置、类型映射、分批策略还有迁移后适配SpringBootMyBatis应用侧踩过的坑。如果你正在做Oracle或MySQL到达梦的迁移或者刚接触达梦数据库、准备用DTS做数据搬迁这篇应该能帮你省下不少弯路。1. 为什么把数据迁到达梦我首选DTS而不是手搓脚本1.1 DTS到底能干什么DTS是达梦数据库官方提供的数据迁移工具一般随达梦数据库安装包一起提供安装时勾选客户端工具组件就能拿到。它做的事情可以简单理解成两件元数据迁移和数据迁移。前者把表结构、视图、存储过程、函数、序列、约束这些对象搬到目标库后者把表里的记录按转换规则写入目标库。相比自己写脚本DTS最大的价值在于“类型映射内置”。比如源库是OracleDTS会知道Oracle的NUMBER对应达梦的什么类型VARCHAR2对应什么DATE对应什么CLOB/BLOB怎么处理。这种映射规则如果自己维护工作量非常大而且很容易漏掉边界情况。DTS是达梦自己做的工具源库和目标库的类型体系都在它的兼容范围内大部分常用类型默认就能转换。另外DTS还提供可视化的任务界面能看到迁移进度的日志哪张表成功、哪张表失败、失败原因是什么都能在任务日志里定位。这一点在手写脚本的“黑盒”方案里是享受不到的排查问题全靠猜。1.2 三种常见迁移方案怎么选我在实际项目中用过三种方式迁数据手工导出导入、通用ETL工具、达梦DTS。简单对比一下方案优势劣势适用场景手工导出CSV/SQL不需要额外工具思路简单类型映射繁琐、大字段难处理、效率低少量临时表一次性清洗通用ETLKettle、DataX等可编排复杂清洗逻辑、扩展性强类型映射要自己维护学习成本高多源汇总、复杂数据清洗链路达梦DTS类型转换内置、支持常见数据库对象、有任务日志主要面向全量迁移图形界面依赖度高Oracle/MySQL/SQLServer到达梦的首次迁移从我踩坑的经验看如果目标库确定是达梦且源库是Oracle、MySQL、SQL Server这类常规关系型数据库用DTS是性价比最高的。自己写程序导入看起来灵活但实际要处理的细节特别多CSV里字段带逗号、换行、转义符怎么办源端NULL和空字符串怎么区分大字段用什么方式写入这些问题DTS已经处理过一轮了没必要从零造轮子。当然DTS也不是银弹。如果需求是持续增量同步比如源库一直在写、目标库要近实时跟上DTS这种偏“全量迁移”的工具并不适合更多要考虑达梦的数据同步方案或者应用层双写。另外如果源库是非关系型或者Hadoop这类大数据组件DTS也不在适用范围内这时候用通用ETL反而更合理。2. 迁移前的准备工作环境、授权、字符集与连接驱动2.1 安装环境差异与DTS组件达梦数据库在Windows和Linux上的安装方式不同DTS的启动方式也不一样。Windows下安装包一般是dm8_xxx_x86_win_64.zip这种名称解压后运行setup.exe图形化向导一路下一步。装完开始菜单里会有“达梦数据迁移工具”的入口直接打开就能用。Linux下安装要麻烦一些得先创建dmdba用户、设置环境变量DM_HOME和PATH、调整系统资源限制然后用安装包目录里的DMInstall.bin执行安装。装完之后如果服务器有图形界面可以进安装目录的tool目录执行./dts启动迁移工具。如果服务器没有图形界面我一般不建议在服务器上硬折腾X11转发更好的做法是在一台Windows客户端机器上装达梦客户端工具然后在客户端上用DTS连接两个数据库完成迁移。DTS本质上是个客户端工具不要求在目标库服务器本机运行只要能同时连通源库和目标库就行。大家都挺常搜的一个点在Linux装完达梦之后找不到迁移工具。这多半是安装的时候没有勾选客户端工具或数据迁移组件。解决方法是重新运行安装程序选择“添加组件”把数据迁移相关组件补上。补装完成后检查安装目录下的tool目录是否存在dts文件夹存在就说明组件到位了。还有一个小提醒网上搜索“DTS下载”时很容易看到另一个叫“KES DTS”的东西那是另一家数据库产品的迁移工具和达梦没有关系别下错装错。2.2 达梦授权key与连接驱动问题达梦数据库启动前需要授权文件dm.key默认路径一般在安装目录下的bin里比如/opt/dmdbms/bin/dm.key。很多人第一次迁移时报错不是数据库配置问题而是试用授权过期或者Key文件缺失。替换Key的操作很简单先把旧Key备份把新的dm.key拷贝到bin目录下覆盖然后重启达梦服务再用disql执行select * from v$license;确认授权信息已经更新。这里注意重启方式要规范如果是通过服务管理的用服务重启命令如果是手动启动的dmserver进程也要正常停止后再启动不要图省事直接kill容易留下数据库恢复隐患。连接驱动是另一个高频搜索点尤其是“Navicat连接达梦数据库”。达梦提供了JDBC驱动核心类是dm.jdbc.driver.DmDriver连接串是jdbc:dm://ip:5236默认端口5236。Navicat要连接达梦关键是把达梦的JDBC驱动jar配置到Navicat的驱动管理里。配置好驱动后用户名通常用SYSDBA注意大小写要正确否则会提示用户名或口令错误。驱动配置不对Navicat会一直卡在连接阶段报“无法连接到数据库”这时候别急着怀疑网络先确认驱动类名和URL写法对不对。2.3 字符集、大小写和模式的坑迁移之前有一件事必须想清楚字符集。达梦在初始化实例的时候会让你选择字符集常见的有UTF-8和GBK。如果源库是GBK目标库建成了UTF-8DTS虽然能做转换但应用连接时如果客户端字符集设置不一致中文很容易变成问号。更麻烦的是如果迁移完才发现乱码数据修复难度极大甚至要重新初始化实例再迁一遍。所以我的习惯是迁移前先用SQL查一下源库的实际字符集比如Oracle可以查SELECT value FROM nls_database_parameters WHERE parameterNLS_CHARACTERSET然后让达梦目标实例的字符集尽量和它一致或者在DTS连接参数里把客户端字符集明确配置好。大小写问题也容易踩。达梦初始化时有个参数CASE_SENSITIVE默认是区分大小写。Oracle用户尤其要注意如果目标达梦也区分大小写应用SQL里表名和字段名的大小写就必须严格匹配。实际项目中我见过太多“明明表名是ADMIN但应用SQL写小写admin报表或视图不存在”的案例。经验是在初始化前就定好策略要么统一用大写对象名应用SQL也别乱用双引号要么初始化时就设置成不区分大小写。DTS在映射目标对象名的时候也会涉及大小写处理如果目标库是敏感的映射时最好明确目标对象名不要让它随手生成带引号的小写名称。还有一个达梦特有的概念用户和模式是严格同名的。Oracle用户SCOTT对应的模式是SCOTT达梦也一样一个用户对应一个同名模式。迁移时如果源端有多个用户或模式目标端最好提前创建好对应的同名用户再在DTS里做“源模式到目标模式”的映射否则所有对象都迁移到一个模式下面后面应用连库查不到对象排查起来很被动。3. 实操全流程Oracle迁达梦8的DTS任务搭建3.1 新建迁移任务的连接配置打开DTS之后界面逻辑和大部分ETL工具类似先建工程再新建迁移任务。工程就是一个任务容器可以保存多个迁移任务方便后续重跑或管理。迁移任务的第一步是配置源库。我这次源库是Oracle连接方式选了JDBC。要填写主机、端口、服务名、用户名和密码端口一般1521。如果DTS连接Oracle时提示找不到驱动需要把Oracle的JDBC驱动jar比如ojdbc8.jar拷贝到DTS安装目录的驱动目录下然后重启DTS。这一步很多人会忽略默认以为工具自带所有驱动实际上不同版本带的驱动有限装完驱动后务必重启工具否则加载不到。第二步是配置目标库。选择达梦数据库填写目标达梦的IP、端口5236、用户名和密码。我习惯先用SYSDBA连接然后在对象映射阶段再指定目标模式。测试连接通过之后进入对象选择界面。这里要提醒一下不要一上来就全选直接跑我建议把迁移拆成两个阶段第一阶段迁结构第二阶段迁数据这样问题定位会清晰很多。3.2 对象选择、类型映射与分批策略对象选择界面会展示源库的模式和对象树。表、视图、序列、存储过程、函数、触发器、约束、索引都在里面。第一阶段我会只勾选结构相关对象比如表结构、视图、序列、存储过程、函数触发器和约束先不勾第一阶段确认目标库里表和视图都创建成功了第二阶段再单独迁移数据。类型映射是DTS的核心操作点。以Oracle迁移到达梦为例几个高频映射要注意Oracle的NUMBER(10,2)DTS一般会映射成达梦的NUMERIC(10,2)数值精度没问题。Oracle的VARCHAR2(4000)到达梦时如果目标数据库初始化页大小是8KVARCHAR(4000)可能会超出长度限制因为达梦的VARCHAR长度受页面大小影响。这种情况下DTS可能自动转成TEXT或CLOB但应用层的查询行为会变需要提前评估。Oracle的DATE达梦的DATE默认是否带时分秒取决于初始化参数。为了保险我习惯把源端的DATE字段映射成达梦的TIMESTAMP避免时分秒丢失。Oracle的LONG、CLOB、BLOB对应达梦的CLOB、BLOB。大字段表迁移时批量提交行数不要设太大否则事务内存占用很高。在DTS的高级设置里可以配置“每批提交行数”。我实测下来大表用5000行一批比较稳妥中小表无所谓。批次太大有两个隐患一是源库读取快照和事务压力增大二是目标库写入失败回滚的代价变大。批次太小则效率上不去。遇到源端业务繁忙时我会把批次调小到2000左右尽量给源库减压。还有个实操经验迁移任务里我一般不勾选唯一约束和索引等数据迁完再手工建。原因很简单数据迁移过程中只要出现重复值、空值唯一约束一触发任务就会报错停下。先迁数据再补约束可以让大任务不被打断如果源端有脏数据最后排查处理。外键约束更是要放到所有数据都迁完之后再建否则父子表数据导入顺序不对就直接失败。3.3 从.sql脚本建库和迁移后的数据校验很多项目拿到的迁移物料不是在线源库而是一堆.sql文件热词里的“中导入.sql”就是这个场景。这里要说明一下DTS更适合“直接连接源库读数据”如果源库已经下线只剩SQL脚本那就没必要用DTS了直接用它内置的disql工具或者达梦管理工具执行脚本更快。disql导入SQL文件的流程是disql SYSDBA/密码localhost:5236 start /opt/scripts/init.sql或者用\i命令执行。如果SQL文件是几个G的大文件建议拆分成多份分批执行避免单条事务过大把回滚段撑爆。Oracle导出的SQL往往会带ALTER SESSION、SET DEFINE OFF、/这类命令头导入达梦之前要清洗一下否则disql可能报语法错误。所以我的建议是如果源库还能连就老老实实用DTS只有当源库彻底不可用时才拿SQL脚本硬跑。迁移完成之后数据校验一定要做。我会写个简单的对比脚本把源库和目标库表的行数逐张查出来源库用Oracle查count(*)目标库用达梦查count(*)然后diff。别只看DTS任务日志显示“成功”很有可能有部分行因为类型转换、长度超限被跳过。行数不一致时去任务日志里搜“错误”和“跳过”基本能找到原因。视图和存储过程的数量也要对比函数、序列一个都不能漏。3.4 迁移后在SpringBoot应用侧适配清单数据迁完只是第一步很多团队卡在应用侧。热词里那个“mybatisdruidspringboot达梦数据库”非常典型我单独说一下。第一换JDBC驱动。达梦8的Java驱动包一般是DmJdbcDriver18.jar对应Java 8以上环境。POM里可以用系统依赖引用dependency groupIdcom.dameng/groupId artifactIdDmJdbcDriver18/artifactId version8.1.3.140/version scopesystem/scope systemPath${project.basedir}/lib/DmJdbcDriver18.jar/systemPath /dependency第二改数据源配置。SpringBoot的application.yml里核心是这样spring: datasource: driverClassName: dm.jdbc.driver.DmDriver url: jdbc:dm://127.0.0.1:5236/MY_SCHEMA username: MY_USER password: xxxx type: com.alibaba.druid.pool.DruidDataSourceURL里最后的MY_SCHEMA是达梦模式名建议写清楚。Druid的filter配置也要注意尤其是在原来MySQL环境下调好的wall拦截规则搬过来之后很可能把达梦的合法SQL给拦了。默认只保留stat这类监控filterwall先关掉等应用跑通再针对性补充规则。第三MyBatis的SQL兼容。Oracle的分页写法是ROWNUM包一层达梦可以直接用LIMIT offset, size。如果项目用了PageHelper要把helperDialect配成dm。主键生成上Oracle习惯用序列.NEXTVAL达梦可以继续用序列也可以用IDENTITY自增列。达梦对Oracle语法做了很多兼容像dual、||拼接这些都问题不大真正容易翻车的反而是保留了字段名比如LEVEL、TYPE、CHECK在SQL里要加双引号或直接改列名。迁移完成后最好把应用里所有SQL在目标库跑一遍冒烟避免上线才暴露语法问题。4. 避坑记录DTS常见报错与排查思路4.1 连接不上、授权失效类问题连接问题最让人头疼的是“看起来配置都对就是连不上”。我整理了一张速查表现象常见原因排查思路目标库连接超时/拒绝达梦服务未启动或端口不对执行ps -ef | grep dmserver用netstat -tlnp | grep 5236确认端口监听Navicat连不上达梦驱动未加载或URL/驱动类配置错误检查dm.jdbc.driver.DmDriver和jdbc:dm://ip:5236DTS提示license/key无效dm.key缺失或过期替换bin/dm.key重启服务查v$license工具页面能开但迁移任务报无权限登录用户权限不足用SYSDBA连接或给迁移用户授予读取元数据的权限连接目标库之前先排除达梦服务本身。Linux下最直接的是ps -ef | grep dmserver有进程说明服务在没有就说明数据库没起来。端口监听也要确认默认是5236如果改了端口DTS和Navicat的连接配置都得同步改。授权key的问题替换起来很快但很多人不知道去哪儿确认是否生效。替换完dm.key并重启服务后用disql执行select * from v$license;看到授权序列号和到期时间更新就说明换成功了。如果还是提示license问题检查一下dm.key文件名大小写、是不是放到了bin目录下以及达梦服务有没有被重启。4.2 乱码、类型转换和数据差异乱码问题在异构迁移里太常见了。源库Oracle是GBK字符集目标库达梦建成了UTF-8DTS虽然能转换但如果客户端连接编码没跟上中文就会变成问号。最有效的办法是迁移前先做个小批量测试迁个几千行数据肉眼检查中文、生僻字、标点符号是否正常确认没问题再跑全量。很多人图省事跳过这一步结果全量跑完才发现编码错只能返工。类型转换导致的失败日志里一般会写清楚是哪张表哪一行报错。Oracle的NUMBER如果没指定精度和scale迁移到达梦时可能生成NUMERIC(38,10)这种默认精度插入大数值时容易报超出范围。我在映射规则里会手工调整纯整数的字段直接映射成NUMERIC(38,0)或者用目标字段类型去适配源端实际数据范围。VARCHAR2(4000)到达梦遇到页大小限制时可以接受自动转成TEXT/CLOB但要在应用侧确认对大字段的读写逻辑。行数不一致是最容易漏的坑。DTS任务日志显示“成功”不等于所有行都进了目标库。数据被跳过有几个常见原因长度超限、类型转换失败、唯一约束命中重复数据、大字段截断。排查方法是去任务日志里搜“错误”“跳过”或者干脆自己写个源库和目标库的count(*)对比脚本。4.3 迁移慢、中断与失败重跑迁移慢是最磨人的。源库在业务高峰跑迁移读快照可能本身就慢目标库如果同时开着归档日志写入压力也大。我的一般做法是业务低峰期执行迁移分批提交设为2000到5000大表按主键范围拆成多个子任务分别跑。比如一张上亿的表可以用WHERE id BETWEEN 1 AND 1000000这种方式切成几十个任务哪个段失败就重跑哪个段不用整个任务从头再来。任务中断之后DTS一般不会自动断点续传。我遇到中断时优先查看任务日志确定已经成功的对象清单然后只对失败的那几张表新开一个迁移任务。只要目标表结构已经存在DTS再次迁移数据不会覆盖没问题的对象聚焦失败表反而更高效。有一回客户源表里有大量重复记录我提前没建唯一索引先把数据全迁了过来再用SQL查出重复数据跟业务确认保留哪条最后清理并重建索引。这个流程比让DTS一遍遍报错要舒服得多。个人习惯是DTS跑完后再花半小时做三件事确认授权状态、核对所有表的行数、把应用关键SQL在目标库跑一遍。数据迁移本质上只是“搬数据”真正决定项目成败的是迁移前的字符集、大小写、类型映射和对象顺序这些决策。这些想清楚DTS用起来比手写脚本省心太多。