必须走逻辑导出+清洗适配+导入流程:①将非innodb表转为innodb;②导出时加--compatible=mysql57等参数;③替换utf8mb4_0900_ai_ci为utf8mb4_unicode_ci、utf8为utf8mb4;④调整sql_mode并验证数据一致性。

不能直接“回退”或就地替换,必须走逻辑导出 + 清洗适配 + 导入流程。MariaDB 10.4+ 的 Aria 系统表、utf8mb4_0900_ai_ci 排序规则、部分函数(如 UNIX_TIMESTAMP(NOW()) 在某些上下文行为差异)和默认 SQL 模式,都会在 MySQL 8.0 中报错或静默失效。
导出前必须确认并转换存储引擎
MariaDB 默认用 Aria 存系统表,还可能在业务表中混用 MyISAM 或 Aria。MySQL 8.0 不识别 Aria,导入时会直接跳过或报错 Unknown storage engine 'Aria'。
- 先查出所有非
InnoDB表:SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE ENGINE NOT IN ('InnoDB') AND TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys'); - 对每张表执行
ALTER TABLE `db`.`tbl` ENGINE = InnoDB;(注意:大表需评估锁表时间) - 导出时加
--skip-triggers --skip-routines --skip-events,避免 MariaDB 特有语法(如IF NOT EXISTS在触发器定义中)干扰
替换排序规则与字符集声明
MySQL 8.0 支持 utf8mb4_0900_ai_ci,但 MariaDB 导出的 SQL 脚本里若含该规则,导入到 MySQL 8.0 虽不报错,却可能因隐式转换导致排序/比较异常;更常见的是反向迁移——MariaDB 导出脚本里用了这个规则,而目标 MySQL 8.0 实例若未启用 Unicode 9.0 数据字典(即 innodb_file_format=Barracuda + innodb_file_per_table=ON),仍可能降级为 utf8mb4_general_ci。
- 导出后、导入前,全局替换脚本中的
COLLATE utf8mb4_0900_ai_ci为COLLATE utf8mb4_unicode_ci(兼容性更强,且 MySQL 8.0 原生支持) - 检查建表语句中是否显式写了
CHARACTER SET utf8—— 这是陷阱,必须改为utf8mb4,否则 emoji 插入失败 - 不要只改
CREATE DATABASE,还要逐个检查CREATE TABLE里的列级CHARACTER SET和COLLATE
处理 SQL 模式与语法断点
MySQL 8.0 默认开启 ONLY_FULL_GROUP_BY 和严格模式,而 MariaDB 10.4 默认关闭。直接导入旧 SQL 可能导致查询报错,或数据被截断(比如插入超长字符串不报错,只静默截断)。
- 导出时加
--compatible=mysql57参数,让mysqldump输出更保守的语法(例如不生成JSON_TABLE或窗口函数) - 导入前,在目标 MySQL 8.0 的配置文件
my.cnf的[mysqld]段手动设置:sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION(明确去掉ONLY_FULL_GROUP_BY,除非你已改造完所有 GROUP BY 查询) - 留意 MariaDB 特有函数:如
REGEXP_LIKE()在 MySQL 8.0 中存在但参数顺序不同;SYSTEM_USER()行为也略有差异,建议统一替换成USER()
导入后必须验证的三件事
行数一致 ≠ 数据一致。checksum 差异往往藏在排序规则隐式转换、时间字段精度截断(MariaDB 默认微秒精度,MySQL 8.0 需显式声明 datetime(6))、以及空字符串与 NULL 的等价判断里。
- 对关键业务表的主键或唯一索引字段,跑一次
CRC32(CONCAT(col1, col2, ...))聚合比对,比CHECKSUM TABLE快且不锁表 - 抽样检查含 emoji、中文姓名、带重音符号的外语名字段,确认排序和
LIKE匹配结果与源库一致 - 执行
SELECT @@sql_mode;和SELECT VERSION();,确认目标实例确实是 MySQL 8.0 且模式已按预期加载
最容易被忽略的是:MariaDB 的 auto_increment 值在导出时可能被 mysqldump 的 --skip-insert-values 类参数影响,导致导入后自增起点错位;务必检查迁移后首条新插入记录的 ID 是否连续,必要时用 ALTER TABLE tbl AUTO_INCREMENT = N; 手动修正。











