
MySQL → 达梦 DM8 数据迁移笔记一、环境说明项目说明源数据库MySQL目标数据库达梦 DM8迁移工具达梦 DTSData Transfer System迁移目标业务系统平滑迁移应用层支持双库兼容运行官方资源DTS 下载https://eco.dameng.com/info/products/dtsDTS 文档https://eco.dameng.com/document/dm/zh-cn/pm/dts_migrate.htmlMySQL JDBC 驱动https://downloads.mysql.com/archives/c-j/二、DTS 迁移整体流程数据库迁移并非简单的数据复制而是结构、数据、约束以及应用适配的完整工程。整体流程如下MySQL │ │ ① 分析源库结构 ↓ DTS 对象转换 │ ↓ DM 建表 │ │ ② 数据迁移 ↓ DM 数据 │ │ ③ 索引 / 约束 / 外键创建 ↓ 应用适配与校验迁移阶段对象迁移读取 MySQL 对象信息根据达梦语法生成对应的建表及对象 SQL。数据迁移负责将源库数据读取并写入达梦数据库。三、迁移前准备清理历史残留如果迁移过程中失败不建议直接重复执行导入任务否则容易产生元数据冲突。常见的残留对象包括表索引唯一约束外键历史数据清理方式可以通过删除用户级联清理或者手动清理已创建的结构与数据DROPUSERDMO_V2CASCADE;四、DTS 迁移常见问题与处理方案1. ON UPDATE CURRENT_TIMESTAMP 兼容问题MySQL 表现CREATE_TIMEtimestampONUPDATECURRENT_TIMESTAMP,UPDATE_TIMEtimestampONUPDATECURRENT_TIMESTAMPMySQL 允许为多个字段设置自动更新时间。达梦限制达梦规定一个表只能存在一个ON UPDATE字段重复定义会抛出错误-2995。处理方案保留UPDATE_TIME用于自动更新将CREATE_TIME仅作为创建时间使用UPDATE_TIMETIMESTAMPONUPDATELOCALTIMESTAMP(0)CREATE_TIMETIMESTAMP2. AUTO_INCREMENT 兼容MySQL达梦id int AUTO_INCREMENTID INT IDENTITY(1,1)或SEQUENCE TRIGGER3. ENGINE、CHARSET、COLLATE 兼容MySQL 语法ENGINEInnoDBDEFAULTCHARSETutf8mb4COLLATEutf8mb4_xxx达梦说明达梦无需上述语法迁移时应直接删除避免语法错误。4. 索引语法兼容MySQL 语法UNIQUEKEYname(name)USINGBTREE达梦语法UNIQUE(name)达梦默认采用 B 树索引因此USING BTREE可以安全移除。5. 唯一约束重复错误 -2864错误信息-2864: 表中已存在这样的唯一关键字或主键原因分析在对象迁移阶段CREATE TABLE时已经创建了唯一索引后续如果再次执行ALTER TABLE ADD UNIQUE就会触发该错误。处理建议迁移前检查约束是否存在SELECT*FROMUSER_CONSTRAINTS;若约束已存在应在迁移任务中跳过重复创建步骤。6. 非空约束失败错误 -6609错误信息-6609: 违反列 [DICT_DESC] 非空约束原因分析达梦表中字段定义为NOT NULL但源数据中存在NULL值。处理方案对源数据进行补齐UPDATExxxSETDICT_DESC暂无描述WHEREDICT_DESCISNULL;7. 外键创建失败错误 -6607错误信息-6607: 违反引用约束原因分析父表中不存在对应的引用数据。典型场景是MySQL 父表有数据达梦父表为空子表先写入数据再创建外键处理建议严格按照以下顺序执行迁移父表 → 子表 → 外键五、应用层双库兼容改造1. MyBatis-Plus 分页方言原问题部分代码硬编码了 MySQL 分页方言newPaginationInnerInterceptor(DbType.MYSQL);这会导致在达梦中仍然生成LIMIT语法从而执行失败。改造方案使用无参构造函数让 MyBatis-Plus 根据当前 JDBC 连接自动识别数据库类型newPaginationInnerInterceptor();涉及文件MyBatisPlusPaginationInnerConfig.javaMybatisPlusConfig.java2. IFNULL 统一替换为 COALESCEMySQL 写法IFNULL(value,)达梦兼容写法COALESCE(value,)建议全局统一替换以保证双库兼容。六、P0 级阻断项处理LIMIT 1 硬编码问题问题描述大量代码直接在 SQL 或 MyBatis 中硬编码了LIMIT 1而达梦不支持该语法。错误做法直接替换为FETCH FIRST 1 ROWS ONLY这会破坏 MySQL 兼容性。正确方案使用 MyBatis-Plus 的分页能力由框架自动生成对应数据库方言PageTpagenewPage(1,1);BI 图表特殊处理避免在 SQL 中绑定分页语法改为在 Java 层处理ListTlistmapper.selectXxx();Tresultlist.get(0);七、P1 级兼容项1. GROUP_CONCAT 替代方案MySQL达梦GROUP_CONCAT(...)LISTAGG(...)推荐方案利用 MyBatis 的databaseId分别维护不同数据库的 SQLselectidxxxdatabaseIdmysqlSELECT GROUP_CONCAT(...) .../selectselectidxxxdatabaseIddmSELECT LISTAGG(...) .../select2. 行标签功能RowTag现状问题当前实现强依赖 MySQL 特性包括元数据查询information_schema.TABLES数据库函数DATABASE()反引号标识符JSON 类型及相关函数AUTO_INCREMENTON UPDATE CURRENT_TIMESTAMPENGINEInnoDB架构优化建议避免通过字符串替换来兼容 SQL应按数据库方言拆分实现RowTagMysqlService RowTagDmService通过策略模式根据当前数据源动态选择对应的实现类。如果觉得有帮助欢迎点赞收藏有问题欢迎评论区交流~