1. 迁移前的摸底:先搞清楚要搬什么、有什么雷
接手一个MySQL迁达梦的活儿,大多数人第一反应是找个工具直接导数据。但真实项目里,真正耗时间的从来不是数据搬运,而是SQL方言差异、数据类型兼容、驱动适配这些藏在后面的问题。我做过一次近两百张表的迁移,前面两天看着工具跑得飞快,后面两周全在改应用层SQL。所以先泼盆冷水:迁移的成败在导数据之前就已经决定了,准备工作做得越细,后面切换那晚就越轻松。
1.1 盘点实例信息:库表清单、字符集、存储引擎与分区表
第一步不是写迁移脚本,而是把源端MySQL的家底摸清楚。别只拿一条select count(*) from information_schema.tables就完事,要按维度拆开看:
- 库表清单与依赖关系:哪些表是主表、哪些是日志表、哪些是字典表,外键关系有多少层。依赖关系会影响迁移顺序,先迁主表、再迁子表,否则外键约束会卡住导入。
- 字符集与排序规则:源库如果用了
utf8mb4_0900_ai_ci这类新版排序规则,达梦不一定认识。建议统一规划目标端字符集,一般初始化为UTF-8,迁移时字符串类型按字节长度重新估算。 - 存储引擎差异:MySQL的InnoDB和MyISAM在锁粒度、事务支持上差别很大,达梦统一使用类似Oracle的表结构。MyISAM表迁到达梦后会获得事务能力,但代价是之前没注意到的隐式提交逻辑要重新审视。
- 分区表:这是容易埋雷的地方。MySQL的RANGE、LIST、HASH分区,达梦都支持,但迁移工具未必能自动转换分区定义。最稳的做法是手动创建目标端分区表,再通过工具只导数据。
- 自增列、默认值、大字段:
AUTO_INCREMENT要对应达梦的IDENTITY,DEFAULT CURRENT_TIMESTAMP要改成DEFAULT SYSDATE,TEXT/JSON要映射为CLOB。这些在数据导入时不会报错,但在应用写入时可能出问题。
1.2 静态扫描SQL风险点:关键字冲突与方言语法
光看表结构还不够,SQL语句才是迁移中最容易出现兼容性问题的环节。建议在迁移前做一次全面的SQL扫描,重点检查以下几类:
- 视图、触发器、函数、存储过程:从
information_schema里把定义全部导出来,逐个过一遍。MySQL的存储过程语法和达梦差异非常大,后面会有专门章节讲。 - 关键字冲突:达梦的保留字集合和MySQL不一样,MySQL里合法的列名
comment、level、rank在达梦里可能直接报错。这类问题静态扫描时就能发现,早期改掉比迁移后改应用成本低得多。 - 隐式类型转换:MySQL对
WHERE varchar_col = 123这种写法很宽容,达梦的隐式转换规则更严格,可能导致索引失效甚至报错。静态扫描时如果看到这种写法,直接标记为高危项。 - 方言函数与语法:
DATE_FORMAT、GROUP_CONCAT、ON DUPLICATE KEY UPDATE、REPLACE INTO这些MySQL特色语法,达梦原生不兼容,需要逐一确认改写方案。
我做迁移项目时,会把扫描结果按P0/P1/P2分级,P0是必须改的语法错误,P1是需改写但结果可等价,P2是性能隐患。这样开发团队的改造工作量可以直接估算出来,后续排期也心里有数。
1.3 数据类型映射表:从MySQL到达梦的对照策略
数据类型的映射不能只靠迁移工具自动完成,工具生成的建表语句往往偏保守,比如把VARCHAR(255)变成VARCHAR(1000),虽然功能没错,但存储空间浪费严重。下面是我在实际项目中验证过的映射方案:
| MySQL类型 | 达梦类型 | 注意事项 |
|---|---|---|
| TINYINT | TINYINT | 布尔语义可用BIT或TINYINT+CHECK |
| SMALLINT | SMALLINT | 无特殊处理 |
| INT / INTEGER | INT | 无特殊处理 |
| BIGINT | BIGINT | 无特殊处理 |
| DECIMAL(p,s) | DECIMAL(p,s) | 精度和标度保持一致 |
| FLOAT / DOUBLE | FLOAT / DOUBLE | 注意浮点精度问题 |
| CHAR(n) | CHAR(n) | 字节长度与字符长度需确认 |
| VARCHAR(n) | VARCHAR(n) | 如果n按字符算,注意达梦按字节上限 |
| TEXT | CLOB | 达梦CLOB支持较完善 |
| LONGTEXT | CLOB | 同上 |
| BLOB / LONGBLOB | BLOB | 二进制大对象直接对应 |
| VARBINARY | VARBINARY | 二进制变长类型 |
| DATE | DATE | 只存日期 |
| DATETIME | TIMESTAMP | 达梦没有DATETIME,用TIMESTAMP |
| TIMESTAMP | TIMESTAMP | 注意默认值和精度 |
| TIME | TIME | 只存时间,达梦支持 |
| YEAR | INT | 用SMALLINT或INT替代 |
| ENUM | VARCHAR(n) + CHECK | 最稳妥,应用层也能处理 |
| SET | VARCHAR(n) | 应用层拆解,不建议保留SET语义 |
| JSON | CLOB | 应用层解析,或用达梦新版本的JSON类型 |
这里特别提醒两点。第一,TEXT映射成CLOB后,有些应用会拿CLOB字段做ORDER BY或GROUP BY,达梦里对CLOB的直接排序有限制,需要改写SQL或用DBMS_LOB处理。第二,MySQL的TIMESTAMP范围到2038年,达梦的范围更大,迁移后如果应用有日期边界判断逻辑,也可能出现行为不一致,属于隐藏坑。
1.4 迁移范围与验收口径:提前定义怎么算"迁完"
很多人迁完数据就宣布完成,结果上线两天发现某个历史报表没迁、某个临时
