引言
在企业数字化转型和国产化替代的浪潮下,从MySQL迁移到达梦数据库(DM)已成为许多项目的关键环节。本文基于实际现场迁移实践,系统梳理MySQL与DM在架构设计、SQL语法、函数使用等方面的典型差异,帮助开发者和DBA在迁移过程中少走弯路,高效完成数据库国产化改造。
一、现场兼容性评估结果
根据现场兼容性测试数据,我们可以得出以下关键结论:
| 测试内容 | 测试项 | DM直接支持 | 需要关注 | 现场结论 |
|---|---|---|---|---|
| 数据类型 | 29项 | 20项 | 9项 | 基础数据类型大部分可以直接迁移 |
| 函数和运算符 | 302项 | 159项 | 143项 | 函数名、参数顺序和返回值差异较多 |
| SQL语法 | 50项 | 11项 | 39项 | MySQL扩展语法是应用改造重点 |
| 分区用例 | 24个主要用例 | 0个直接照搬 | 24个需转换或改写 | 复杂分区定义是数据对象迁移重点 |
重要说明:表中的"不支持"通常指"MySQL原语法不能直接在DM执行",不代表DM没有相同功能。很多项目可以通过DTS自动转换、DM替代函数、虚拟列、分析函数或存储过程实现。
现场结论:MySQL到DM迁移中,普通表数据及基础数据类型总体兼容度较高,主要改造工作集中在数据库组织架构、MySQL扩展SQL、内置函数、存储过程以及复杂分区对象等方面。
二、架构层面的典型区别
这是迁移过程中最需要重点规划和调整的部分。
1. 数据库组织架构对比
| 比较项 | MySQL | DM | 现场迁移处理 |
|---|---|---|---|
| 数据库组织 | 一个实例中通常包含多个database | 一个目标数据库实例中通常包含多个用户和模式 | 按MySQL业务库逐个迁移到对应DM用户/模式 |
| 用户与对象关系 | 用户和数据库相对独立,一个用户可以访问多个库 | 对象归属于模式,现场通常建立与模式同名的业务用户 | 创建业务用户、同名模式和独立表空间 |
| 对象访问方式 | 数据库名.表名 | 模式名.表名 | 将dbtest.user_info改为DBTEST.USER_INFO |
| 数据库切换 | 使用USE dbtest切换当前库 | 通常使用SET SCHEMA DBTEST切换当前模式 | 应用初始化SQL和脚本需要修改 |
| 存储组织 | 表可以指定ENGINE=InnoDB、ROW_FORMAT等属性 | 不采用MySQL式的表级存储引擎配置 | 删除或重新设计ENGINE、ROW_FORMAT等属性 |
| 字符集与排序规则 | 可在数据库、表、字段级设置字符集和COLLATE | 更多依赖实例初始化参数、字符集和CASE_SENSITIVE | 迁移前统一规划字符集、大小写和长度语义 |
2. 架构映射示例
MySQL源端架构:
MySQL实例 ├── order_db ├── customer_db └── report_db迁移到DM后通常规划为:
DM实例 ├── ORDER_DB用户/模式 → ORDER_DB表空间 ├── CUSTOMER_DB用户/模式 → CUSTOMER_DB表空间 └── REPORT_DB用户/模式 → REPORT_DB表空间3. 操作逻辑变化
MySQL操作:
-- MySQLUSEorder_db;SELECT*FROMorder_info;DM对应操作:
-- DMSETSCHEMAORDER_DB;SELECT*FROMORDER_DB.ORDER_INFO;4. 架构差异带来的具体影响
- 应用连接:连接DM时,需要明确连接用户和默认模式
- 跨库访问:原来跨MySQL数据库访问的SQL,需要改为跨DM模式访问
- 权限管理:权限需要按照用户、模式和对象重新授予
- 存储规划:不能把多个业务库的数据全部迁入SYSDBA模式和MAIN表空间
- 前期准备:表空间、业务用户和模式应在正式迁移前规划完成
三、SQL语法层面的典型区别
从现场兼容性表看,SQL语法是改造量最大的部分之一。重点不是普通的SELECT/INSERT/UPDATE/DELETE,而是MySQL在这些语句基础上增加的扩展写法。
1. 数据库与模式语法
| MySQL | DM改造 |
|---|---|
CREATE DATABASE dbtest | CREATE SCHEMA DBTEST,同时规划用户及表空间 |
USE dbtest | SET SCHEMA DBTEST |
DROP DATABASE dbtest | DROP SCHEMA DBTEST |
dbtest.table_name | DBTEST.TABLE_NAME |
注意:MySQL中DATABASE和SCHEMA在不少语句中属于同义概念,但迁移到DM后应按照DM的用户、模式、表空间体系重新设计。
2. 字符串与对象名处理
MySQL默认模式下允许使用双引号表示字符串,但DM中应统一使用单引号,双引号主要用于引用对象名。
MySQL原写法:
SELECTCONCAT(",",MODEL_KEY,",");DM推荐写法:
SELECTCONCAT(',',MODEL_KEY,',');对象名大小写规则:
- DM未加双引号的对象名通常转为大写:
CREATE TABLE user_info(id INT);对应USER_INFO - 如果创建:
CREATE TABLE "user_info"(id INT);后续引用时一般也必须保持双引号和大小写
现场建议:优先统一对象名,不建议大量保留混合大小写对象。
3. 布尔表达式作为查询结果
MySQL可以直接返回比较表达式结果:
SELECT2>1;在DM中,作为查询列返回时,通常改为:
SELECTCASEWHEN2>1THEN1ELSE0ENDFROMDUAL;同类改造包括:
SELECT col IN (1, 2, 3);SELECT col BETWEEN 1 AND 10;SELECT EXISTS(SELECT 1 FROM t);
注意:当这些表达式位于WHERE条件中时通常可以直接使用;当表达式作为查询结果返回时,需要重点测试。
4. MySQL用户变量改造
MySQL常使用@变量进行赋值、累计和排名:
SELECTid,@total:=@total+amountFROMorders,(SELECT@total:=0)tORDERBYid;DM中通常使用分析函数:
SELECTid,SUM(amount)OVER(ORDERBYidROWSUNBOUNDEDPRECEDING)AStotal_amountFROMorders;如果是存储过程变量,则在DM过程声明区中定义:
DECLAREV_TOTALDECIMAL(18,2);BEGINV_TOTAL :=0;END;/这类改造比简单函数替换更重要,因为它涉及SQL执行逻辑。
5. 日期时间函数差异
现场表中DATE_ADD、DATE_SUB、DATEDIFF、STR_TO_DATE、YEARWEEK、PERIOD_DIFF等均存在差异。
DATE_ADD函数:
-- MySQLSELECTDATE_ADD(order_date,INTERVAL1DAY);-- DMSELECTDATE_ADD(order_date,INTERVAL'1'DAY);DATEDIFF函数:
-- MySQLSELECTDATEDIFF(end_date,start_date);-- DM方式一SELECTDATEDIFF(DAY,start_date,end_date);-- DM方式二SELECTDAYS_BETWEEN(end_date,start_date);字符串转日期:
-- MySQLSELECTSTR_TO_DATE('2026-08-06 10:20:30','%Y-%m-%d %H:%i:%s');-- DMSELECTTO_DATE('2026-08-06 10:20:30','YYYY-MM-DD HH24:MI:SS');日期函数改造要点:同时检查函数名称、参数数量、参数顺序、日期格式模板、时间间隔单位、NULL及非法日期处理结果。
6. 字符串聚合函数
MySQL GROUP_CONCAT:
SELECTdepartment_id,GROUP_CONCAT(employee_nameORDERBYemployee_name SEPARATOR',')FROMemployeeGROUPBYdepartment_id;DM LISTAGG:
SELECTdepartment_id,LISTAGG(employee_name,',')WITHINGROUP(ORDERBYemployee_name)FROMemployeeGROUPBYdepartment_id;7. 多表删除语法
MySQL多表删除:
DELETEFROMaUSINGtable_a a,table_b bWHEREa.id=b.idANDb.status=0;DM改写:
DELETEFROMtable_a aWHEREEXISTS(SELECT1FROMtable_b bWHEREb.id=a.idANDb.status=0);8. 插入冲突处理
MySQL常见写法:
-- 忽略重复INSERTIGNOREINTOtVALUES(...);-- 替换插入REPLACEINTOtVALUES(...);-- 冲突更新INSERTINTOtVALUES(...)ONDUPLICATEKEYUPDATEname=VALUES(name);DM中通常根据业务语义改写为MERGE:
MERGEINTOtarget_table tUSINGsource_table sON(t.id=s.id)WHENMATCHEDTHENUPDATESETt.name=s.nameWHENNOTMATCHEDTHENINSERT(id,name)VALUES(s.id,s.name);重要提醒:MySQL的REPLACE本质上可能涉及"删除旧记录后重新插入",与MERGE UPDATE在触发器、自增值和级联关系上的副作用并不完全相同,不能只做机械替换。
9. 存储过程和函数差异
这是DM更接近Oracle、与MySQL差异最明显的部分。
| MySQL | DM |
|---|---|
RETURNS | RETURN |
| BEGIN后声明变量 | 通常在BEGIN前的声明区声明 |
DECLARE CONTINUE HANDLER | 使用异常处理或游标%NOTFOUND |
LEAVE | EXIT |
ITERATE | CONTINUE |
PREPARE/EXECUTE | EXECUTE IMMEDIATE |
| 过程内直接执行部分DDL | 通常改为动态SQL |
IF()函数 | CASE WHEN或过程IF语句 |
@用户变量 | 局部变量、参数或分析函数 |
示例改造:
MySQL存储过程:
CREATEPROCEDUREP_TEST()BEGINDECLAREV_COUNTINTDEFAULT0;TRUNCATETABLETEST;END;DM存储过程:
CREATEORREPLACEPROCEDUREP_TESTASV_COUNTINT:=0;BEGINEXECUTEIMMEDIATE'TRUNCATE TABLE TEST';END;/四、分区表迁移要点
从兼容性测试看,分区表是迁移的重点和难点:
- 分区策略差异:MySQL的分区语法与DM存在显著差异
- 自动转换有限:DTS工具对复杂分区定义转换能力有限
- 性能考虑:需要重新评估分区键和分区策略
- 维护操作:分区维护语句需要重写
建议做法:
- 简单范围分区:通常可以直接迁移
- 复杂分区(LIST、HASH、复合分区):需要重新设计
- 分区维护操作:需要重写为DM语法
五、迁移最佳实践建议
1. 迁移前准备
- 完成全面的兼容性评估
- 制定详细的迁移方案和回退计划
- 统一规划字符集、大小写敏感性和对象命名规范
- 提前创建好用户、模式和表空间
2. 迁移过程
- 使用DTS工具进行结构和数据迁移
- 对无法自动转换的对象和SQL进行手动改造
- 分模块、分批次迁移,降低风险
- 建立完整的测试用例,确保功能一致性
3. 迁移后验证
- 数据一致性验证
- 性能对比测试
- 应用功能回归测试
- 监控系统运行状态
4. 常见问题处理
- 连接问题:检查连接字符串、用户权限和模式设置
- 性能问题:优化SQL、调整索引和分区策略
- 兼容性问题:使用DM的兼容模式或改写SQL
六、总结
MySQL到DM的迁移不仅仅是简单的数据搬迁,更是一次架构重构和语法适配的过程。通过本文梳理的典型差异,我们可以看出:
- 架构差异是基础:需要重新理解DM的用户-模式-表空间体系
- SQL语法是重点:特别是MySQL的扩展语法需要重点改造
- 函数差异是常态:需要建立函数映射表和改造规范
- 存储过程是难点:需要深入理解两种数据库的过程语言差异
成功的迁移需要技术团队对两种数据库都有深入的理解,结合自动化工具和手动改造,在保证业务连续性的前提下,平稳完成国产化替代。
最后建议:在正式迁移前,务必进行充分的POC测试,建立完整的迁移知识库和问题解决方案库,为大规模迁移积累经验。