很多做数据库迁移的朋友看到“MySQL到达梦”几个字第一反应就是“又是个大工程”。实际上这两年在配合业务做数据库迁移时我接触最多的反而是几十张表、单表几十万行的中小型业务库。这类体量只要网络正常、对象结构别太离谱真正从连接源端到迁移执行完三分钟内跑完完全有可能。今天就把我反复跑过的一套流程拆开来讲三分钟是哪一部分的三分钟、动手前要做什么、两条实际可用的迁移路径以及迁移完之后最容易忽略的校验和排错环节。1. 先弄明白“三分钟迁移”到底是哪三分钟1.1 我实际接触的MySQL到达梦迁移场景这两年配合业务方做过的MySQL到到达梦数据库切换大概能分成三类。一类是业务系统重新选型不再用原本的MySQL实例一类是公司里MySQL实例太多想逐步统一到一个数据库平台上管理还有一类是新项目直接落在达梦上需要把老MySQL库里积累的历史数据搬过来做初始化。这些场景有个共同特点都不是那种几百亿行、秒级写入的核心账务库而是几十张表、结构相对规范、单表数据量在几十万到几百万行的普通业务库。这种体量下只要迁移链路本身是通的数据搬运这个执行阶段确实能做到分钟级。真正耗时的是搬之前的对象盘点以及搬完之后的数据校验和应用SQL兼容性改造。如果上来就对着一个几千万行的大表谈“三分钟”那肯定不现实这个问题我会在第5章专门讲清楚。1.2 三分钟的真实边界我在说“三分钟快速迁移”的时候心里其实是有一个默认前提的源端MySQL连接信息明确目标端达梦实例已经初始化好账号权限已放通待迁对象的基本情况已经盘点过。在这个前提下用达梦自带的DTS迁移工具从连接源端、勾选对象、开始执行到跑完一个小规模库是可以控制在几分钟内的。如果把建库、建用户、调服务参数、应用改造都算进去那按小时甚至按天算都正常。所以建议你先对号入座如果你手头的库是几十张表、表中没有大字段、没有几十个存储过程那值得按“三分钟迁移”的思路来准备如果你的库单表超千万行、分区表一大堆、应用里全是MySQL专有函数那就别指望净迁移三分钟了老实用分批迁移加增量同步的方案。1.3 迁移方案选择的判断标准我每次迁移前都会先回答三个问题能不能停库目标端是不是只有自己用应用能不能接受短期数据不一致。能停库、目标端是测试环境直接走全量迁移最省事DTS一跑校验通过收工。不能停库、源端还在持续写入那就别想着一次把所有数据搬完。先做结构迁移再在低峰期做一次静态数据导出如果讲究一点还要配增量同步来追平停机窗口期间的新数据。这个问题想不清楚后面所有步骤都可能白做。2. 动手前把这三件事做了迁移才会快2.1 连接信息与目标模式登记表我不太相信记忆力每次迁移前都会做一张信息登记表先确认源端和目标端的基本信息再动手去连。项目源端MySQL目标端达梦实例地址10.10.x.x:330610.10.y.y:5236数据库/模式名companydbCOMPANY登录账号readonly_userSYSDBA字符集utf8mb4UTF-8待迁对象全部表和视图提前建好的目标模式这张表看着简单但很多迁移翻车都发生在目标端模式名写错、源端账号权限不够这些低级问题上。建议每填一行就在对应环境里执行一条实际语句验证一次不要凭记忆猜。比如源端用mysql -u账号 -p -e show databases确认连通性和可见库目标端用达梦的disql执行一句select 1 from dual;确认能连上。2.2 对象清单盘点能自动迁的和必须手工改的在源端我会跑两条SQL把库里的表、视图、存储过程、函数、触发器全部列出来。表的部分重点看有没有自增列、JSON字段、二进制大字段、分区表函数和存储过程部分重点看有没有用到MySQL独有的语法。看完之后给对象分三档第一档是标准表DTS基本能自动迁第二档是结构特殊一点的比如自增列、特殊默认值迁移后需要人工核对建表语句第三档是存储过程、函数、触发器里用了group_concat、date_format、ifnull这类MySQL习惯写法的基本都要手工改造。把这些预先标出来绝对比等导入报错再翻日志快得多。2.3 权限准备与连通性验证源端MySQL账号至少要能全表select如果库里有视图和触发器还得有show view和trigger权限。目标端达梦账号需要有建表、建索引、建视图的权限。如果目标模式还没建先用管理员账号建好模式、赋好权限不要等到DTS执行到一半才想起来权限不足。这部分有个很容易忽略的点MySQL和达梦的默认端口不一样如果目标实例在另一台机器上务必提前确认防火墙放行了5236端口。网络不通的时候DTS界面会一直转圈非常浪费时间。连通性测试宁可多做一次也不要等到迁移任务超时再回头查。3. 三分钟迁移实操两条路径任选3.1 路径A达梦DTS迁移工具的可视化迁移DTS是达梦安装包自带的图形化迁移工具。它在“MySQL到达梦”这个方向做了不少默认处理比如把MySQL的反引号标识符转换掉把AUTO_INCREMENT映射成达梦的IDENTITY自增列把datetime映射成时间戳类型。这也是为什么我遇到中小型库首选一定是DTS。实际操作逻辑大致是这样的启动DTS新建工程新建一个迁移任务源数据库类型选MySQL填源端连接信息目标数据库类型选DM填目标实例连接信息勾选需要迁移的对象第一次建议只勾表和视图不勾存储过程在类型映射界面逐项检查一遍看到带感叹号的对象就点开手动确认设置批量提交行数和出错处理方式然后点执行。执行过程中DTS会逐表显示迁移状态。我印象里单表几十万行的普通表一张大概跑几秒到十几秒几十张表不加存储过程的话整个任务跑完也就一两分钟。跑完后它会生成迁移报告哪张表失败、失败在哪条SQL都能看到。这里有个关键心法别把希望全压在DTS上。迁移完不等于结构完全一致。我每次跑完都会在目标端挑几张典型表看建表语句重点确认自增列、默认值、字段注释。如果发现工具把某个字段类型映射得和自己预期不一致下次迁移前先手动调整目标表用不了两分钟却能省掉应用层的一堆报错排查时间。3.2 路径Bmysqldump导出加DISQL导入的命令行方案在没有图形界面的服务器上或者想把迁库过程写进自动化脚本里走命令行更顺。我的做法分三步。第一步在MySQL端导出数据mysqldump -h10.10.x.x -P3306 -u账号 -p \ --single-transaction --skip-lock-tables \ --default-character-setutf8mb4 \ --no-tablespaces companydb companydb.sql--single-transaction能保证导出期间InnoDB表读到的是一致性快照不会锁住业务表--no-tablespaces是去掉表空间相关语句避免达梦不识别。第二步对SQL文件做轻量清洗。最常见的是建表语句末尾的ENGINEInnoDB DEFAULT CHARSETutf8mb4子句以及AUTO_INCREMENT。我习惯写个小脚本处理正则不建议手工改大文件。文件里如果出现大量反引号尽量去掉达梦会把双引号当标识符引用符反引号基本不受支持。第三步用DISQL导入/opt/dm/bin/disql SYSDBA/密码localhost:5236 SQL start /backup/companydb.sql这个方案比DTS多几步但胜在可控。导出文件有问题可以只改文件重新执行不用每次都在图形界面里重新勾一遍对象。它也比较适合“把数据导到文件再交给别人到目标环境导入”的工作模式。缺点是SQL语法兼容性需要自己打理如果源库建表语句里带了太多MySQL习惯写法清洗脚本要反复迭代几次才能稳定。3.3 让执行阶段快起来的三个控制点无论DTS还是命令行导入真正影响迁移耗时的就是三个变量网络往返、单条SQL执行开销、事务提交频率。第一批量提交。DTS里的“批记录数”我一般设5000到10000。设太小每条记录都走一次提交慢设太大目标端日志压力上来反而卡。命令行导入SQL文件的话可以在清洗阶段就把多行insert合并成一条减少解析和执行次数。第二临时关闭外键校验。有父子表关系的库按默认顺序导数据时外键约束很容易拖后腿甚至报错。DTS里可以勾选“导入数据时忽略外键”也可以先只迁移表结构等数据导完再补外键约束。顺序上我永远是“先结构、后数据、再约束”。第三确认目标端日志参数不是最低配置。导入期间如果目标库的日志频繁切换整个吞吐会明显下降。这属于达梦实例初始化层面的设置建议迁移前就确认好而不是数据导到一半再去调整。4. 数据搬完只是上半场校验与收尾4.1 三层数据校验行数、总和、抽样数据迁移完的第一件事不是关窗口而是做数据校验。我习惯分三层来查。第一层逐表对比行数。在两个库分别执行SELECT COUNT(*) FROM 表名;表多了以后用脚本循环执行把结果写入文件后对比。手工一张张查不现实也容易漏。第二层数值字段总和对比。针对订单金额、库存数量这类关键数值列在两个库各跑一遍同样的求和SQL结果一致基本能排除类型转换把精度吃掉的情况。第三层随机抽样全字段对比。我会在主键范围的首、中、尾各取一条再随机取十几条逐字段核对字符串、时间、小数位。这个环节最好写成SQL用两个库的同名表做连接把不一致的记录筛出来而不是肉眼一行行看。4.2 对象级回归索引、约束、视图、存储过程数据没丢不等于对象没问题。第2章盘点过的对象清单这时候要拿出来逐项打钩。索引的数量和定义直接影响后续查询性能。外键约束漏掉一个应用层就会出现“数据明明在业务却跑不动”的情况。视图和存储过程更麻烦DTS通常只能迁一部分迁完也必须逐条手工验证。我的习惯是把存储过程在目标端重新编译一遍看有没有语法报错再挑两三个最关键的存储过程实际调用一次看返回结果是否和源端一致。对象级这块是最费时间的但也是判断迁移是否真正完成的核心标准。4.3 应用连接串切换前的体检数据面和对象面都过了还要检查应用连接串。MySQL的JDBC URL和达梦的JDBC URL差异很大驱动更是两回事。如果业务系统是Java要把驱动替换成达梦自带的JDBC驱动URL改成类似jdbc:dm://10.10.y.y:5236的格式同时去掉characterEncoding、useSSL这些MySQL专用参数。连接串改完别急着全量切流。先用一个最小工具直接连目标库验证基本读写再安排一个应用实例切过去跑几分钟重点看日志里有没有SQL报错。统计上结构迁移和数据迁移都通过不代表应用里那几百条SQL全兼容。应用真的跑通了迁移才算真正告一段落。5. 实测踩过的坑五类问题与完整排查链路5.1 自增列和默认值迁移后插入新数据报主键冲突MySQL习惯写id int auto_increment primary key到达梦后最稳的写法是id int identity(1,1) primary key。DTS一般能处理但命令行导入时如果建表语句是自己写的很容易漏掉identity。漏掉的后果是历史数据导进去了应用插入新记录时主键冲突。排查最快的方法就是看目标端建表语句确认identity在不在不在就重建表或手工补上。5.2 表名大小写与标识符引号MySQL在Linux下默认表名小写达梦默认会把未加引号的标识符统一转成大写。应用如果写的是小写表名一般能匹配但如果用驼峰命名或者建表时用了双引号大小写就会变得极其敏感。这个问题的根治思路是在达梦实例初始化阶段就想清楚大小写策略建库前定规则不要等数据迁完才发现应用SQL对不上。5.3 字符集乱码文件的编码和库的编码必须一致导出文件是UTF-8目标库字符集不是UTF-8中文基本就会乱。另一种常见情况是源端MySQL字段实际用了latin1导出时又强制指定utf8mb4数据经过双重转换后各种怪字符。排查乱码时我会卡三个阶段MySQL连接字符集、导出文件的实际字节、达梦客户端导入时的字符集设置。用file命令看一眼导出文件编码再用十六进制工具看中文字节基本能定位是哪一环出了问题。5.4 大事务卡住与锁等待有一次导一张接近百万行的表跑到三分之一就停住不动。我第一反应是看DTS日志报的是锁等待超时。再看目标端原来有个测试连接一直在占着表锁。处理方法是把占用锁的会话停掉DTS任务重新跑并把批提交行数从默认值调到5000问题解决。这类问题如果发生在生产环境千万别直接重启数据库。先查活动会话和事务确认是谁持有锁再做针对性处理。迁移过程中的卡顿十有八九是锁和事务提交频率的问题不是数据量的问题。5.5 函数差异不一定会报错但结果可能是错的比语法报错更棘手的是“不报错但结果不对”。MySQL的concat和达梦都能用但null处理逻辑不同MySQL的ifnull到达梦要改写成nvl或coalesce日期格式化函数两边写法差异更大。我建议应用迁过来后不要只看接口通不通还要找几条曾经触发过特殊条件的历史数据实际跑一遍确认函数返回值和原来一致。这种隐性差异最需要时间沉淀也是迁移项目里最容易被低估的部分。5.6 把一次卡顿的完整排查链路走一遍把上面的经验串成一条排查链路大概是这样的看到迁移工具日志定位到具体表 → 在目标端查当前活动事务和锁等待 → 确认锁源是应用连接还是迁移进程 → 如果是迁移进程调小批提交、临时关闭外键校验再重试 → 如果还不行把该表数据单独导出导入排除某一行特殊数据导致整个事务回滚的可能。这套顺序我用了很多次。每次都能把问题范围缩小到“结构问题”还是“数据问题”还是“并发问题”这个层级然后快速处理。6. 快速迁移的边界和我的个人习惯6.1 哪些场景不该追求三分钟有几种情况我会明确告诉业务方别指望净迁移三分钟。单表超过千万行且带大字段源端MySQL还在高并发写入存储过程一大堆且大量依赖MySQL特有的动态SQL目标达梦实例还没做初始化调优这些场景硬上全量快速迁移风险远大于收益。更合理的做法是先做结构迁移再做分批数据迁移配合增量同步追平数据最后开一个短切换窗口。这种思路下整体迁移周期会拉长但每一步都稳回滚也容易。数据库迁移最怕的不是慢是边迁边出乱子。6.2 迁移完成后的两个小习惯第一件把迁移任务本身写成一份可重复执行的checklist从信息登记、权限检查到行数校验、对象回归全都列进去。下次再遇到类似任务照着走一遍效率高很多也不容易漏项。第二件迁完以后别急着走把目标库当全新环境来跑一遍重点功能尤其涉及日期、金额、字符串拼接的页面。数据库迁移不是数据过去就结束应用真正能用起来才算完成。最后再分享一个实际体会三分钟快速迁移能不能成立很大程度上取决于源端表结构规不规范。表结构越规范前期准备越短执行越顺那些默认值混乱、字段类型满天飞的库前期清理半小时都未必够。所以别盲目相信任何迁移工具先把对象清单做清楚再按这套流程走一遍三分钟做一个干净的MySQL到达梦迁移是完全可以实现的。