mysql在迁移过程中解决数据库版本不兼容问题

来源:这里教程网 时间:2026-02-28 20:45:30 作者:

mysqldump 导出时指定兼容版本参数

MySQL 5.7 和 8.0 的默认 SQL 模式、保留字、JSON 字段处理方式差异较大,直接用高版本

mysqldump
导出再导入低版本会报错,比如
Unknown column 'json_col' in 'field list'
You have an error in your SQL syntax
。关键不是“能不能导”,而是导出的 SQL 是否带目标版本不支持的语法。

使用

--compatible
参数可强制降级语法输出:

mysqldump --compatible=mysql40 --skip-triggers --no-tablespaces -u root -p mydb > mydb.sql

常用值有:

mysql40
(兼容 4.0+)、
ansi
(ANSI SQL 标准)、
postgresql
(仅语法适配,不推荐)。注意:
--compatible
不影响数据类型映射,比如 MySQL 8.0 的
JSON
类型仍会导出为
JSON
,需手动替换成
TEXT
并关闭校验。

--skip-triggers
避免触发器中使用
NEW.col
等 5.7+ 才支持的写法
--no-tablespaces
防止导出
TABLESPACE
子句(MySQL 5.7 默认禁用)
不要加
--set-gtid-purged=ON
(8.0 默认开启),低版本不识别该语句

导入前手动清理高版本特有语法

即使用了

--compatible
,某些结构仍无法自动降级:比如 MySQL 8.0 的隐藏主键(
INVISIBLE PRIMARY KEY
)、角色权限语句(
CREATE ROLE
)、默认字符集
utf8mb4_0900_as_cs
。导入时会卡在第一条非法语句并报错退出。

建议用

sed
或脚本预处理 SQL 文件:

sed -i 's/INVISIBLE //g; s/ALGORITHM=INSTANT//g; s/utf8mb4_0900_as_cs/utf8mb4_general_ci/g' mydb.sql

重点检查并替换以下内容:

CREATE TABLE ... JSON
→ 改为
TEXT
并删除
JSON_VALID()
约束
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
→ 拆成两个独立子句(5.6 不支持复合写法)
所有
ROLE
SET PERSIST
ADMIN OPTION
相关语句整行删除
ENGINE=InnoDB ROW_FORMAT=DYNAMIC
中的
ROW_FORMAT
可删(5.6 默认 DYNAMIC,但不认该关键字)

字符集与排序规则必须显式降级

MySQL 8.0 默认字符集是

utf8mb4
,排序规则是
utf8mb4_0900_as_cs
;而 5.7 最高只支持
utf8mb4_unicode_ci
。如果导出 SQL 中保留了 8.0 的排序规则,导入时会提示
Unknown collation: 'utf8mb4_0900_as_cs'
,且不会跳过,直接中断。

不能依赖

--default-character-set=utf8mb4
,它只影响客户端连接,不改表定义中的
COLLATE
。必须全局替换:

sed -i "s/utf8mb4_0900_as_cs/utf8mb4_unicode_ci/g; s/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g" mydb.sql

同时确认目标库已启用

utf8mb4
支持:

SET NAMES utf8mb4;
ALTER DATABASE mydb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

否则即使 SQL 通过,插入中文可能乱码或截断。

权限迁移需重建而非导出

mysqldump --all-databases
不导出
mysql
系统库(除非显式加上),而权限信息全在
mysql.user
mysql.db
表里。即便你 dump 了系统库,MySQL 8.0 的
authentication_string
字段加密方式(caching_sha2_password)和 5.7(mysql_native_password)不兼容,直接导入会导致用户无法登录。

正确做法是:在目标低版本上,用

SHOW CREATE USER
SHOW GRANTS
生成可执行语句,再手动调整认证插件:

CREATE USER 'appuser'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
GRANT SELECT,INSERT ON mydb.* TO 'appuser'@'%';

要点:

避免用
mysqldump mysql
迁移权限,风险极高
8.0 用户若用
caching_sha2_password
,必须在创建时显式指定
IDENTIFIED WITH mysql_native_password
导入后执行
FLUSH PRIVILEGES
,否则新权限不生效

版本降级迁移最易忽略的是隐式行为变更:比如 8.0 中

GROUP BY
默认严格,5.7 允许 select 列不在 group by 中;又比如 8.0 的
ONLY_FULL_GROUP_BY
开关位置变了。这些不会报错,但查询结果可能不一致——得靠业务验证,不能只看导入成功。

相关推荐