最近把一个项目的 MySQL 从 8.0.28 升级到了 8.4.7。表面上看是跨了一个小版本号,但 8.4 是 MySQL 首个正式的 LTS(长期支持)版本,和 8.0 之间存在着不少 breaking changes。8.0 的常规支持已经在 2026 年 4 月结束,继续停留在 8.0 意味着后续安全更新和 bug 修复会越来越少。升级势在必行,但过程并不像想象中那么平滑。
这篇文章把整个升级过程中遇到的问题和排查思路记录下来,给同样在做这个升级的同行一个参考。
升级前的准备
正式动手之前,官方文档明确建议先用 MySQL Shell 的升级检查器跑一遍兼容性评估:
util.checkForServerUpgrade('root@localhost:3306', {targetVersion: '8.4.7'})
这个工具会扫描当前 8.0 实例并输出详细的兼容性报告,覆盖数据字典兼容性、废弃系统变量、SQL 语法兼容性、认证插件等问题。建议无论如何都要跑一遍,能提前暴露大部分问题。
除此之外,备份是绝对不能跳过的步骤。物理全量备份加逻辑导出双管齐下,并且一定要验证备份文件的可恢复性。
问题一:认证插件不兼容(ERROR 1524)
这是升级过程中最典型的拦路虎。
升级完成后,应用连接 8.4 实例时报错:
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded
但主库 8.0 连接一切正常。
原因分析:MySQL 8.4 默认禁用了 mysql_native_password 服务端认证插件。这个插件从 8.0.34 开始已被标记为废弃,到 8.4 默认不再加载。而很多从 5.7 或早期 8.0 迁移上来的系统,用户账号仍然使用 mysql_native_password 作为认证方式。用 mysqldump 全量备份再导入 8.4 时,mysql.user 表中的用户信息被原样带入,但 8.4 不加载该插件,导致认证失败。
解决方案:分两种场景处理。
临时方案——如果只是为了尽快完成升级验证,可以在 8.4 的配置文件 my.cnf 中临时启用该插件:
[mysqld]
mysql_native_password=ON
重启服务后即可兼容旧账号。但这个方案只是过渡,因为该插件在 MySQL 9.0 中会被彻底移除。
长期方案——在升级前或升级后将所有用户账号迁移到 caching_sha2_password:
ALTER USER 'username'@'host' IDENTIFIED WITH caching_sha2_password BY 'password';
同时确认客户端驱动版本支持 caching_sha2_password(JDBC 驱动需 8.0 以上,Connector/Net 需 8.0.28 以上)。
问题二:字符集遗留问题
升级检查器报告了一些表仍在用 utf8mb3(即 utf8 别名)。
MySQL 8.4 中 utf8mb3 已被标记为废弃,虽然当前 LTS 版本仍支持,但未来主版本会被移除。官方建议尽早迁移到 utf8mb4。
检查哪些表还在用旧字符集:
SELECT table_schema, table_name, table_collation
FROM information_schema.tables
WHERE table_collation LIKE 'utf8%' AND table_collation NOT LIKE 'utf8mb4%';
迁移操作:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意 utf8mb4 每个字符占 4 字节,而 utf8mb3 占 3 字节,VARCHAR 索引长度限制需要提前评估。
问题三:AUTO_INCREMENT 不当使用
升级检查器还标记了一个问题:某张表的 FLOAT 类型列使用了 AUTO_INCREMENT。
MySQL 8.4 不再允许 FLOAT 和 DOUBLE 列使用 AUTO_INCREMENT 属性。这个功能在 8.0 中已被弃用,到 8.4 彻底移除。如果表结构中有这种组合,升级会直接失败。
检查方法:
SELECT table_schema, table_name, column_name, data_type
FROM information_schema.columns
WHERE extra LIKE '%auto_increment%'
AND data_type IN ('float', 'double');
解决方案是将这些列改为整数类型(如 INT 或 BIGINT),或者移除 AUTO_INCREMENT 属性改用其他标识方案。
问题四:外键约束变更
升级前检查还发现了一个潜在风险:部分外键引用的父表列并非唯一键。
MySQL 8.4 对外键的要求更严格了——父表被引用的列必须拥有唯一键。升级过程中服务器会打印警告信息,列出所有引用非标准键的外键名称。虽然当前版本升级不会直接失败,但未来版本可能会变成硬性错误。
建议在升级前 review 所有外键定义,确保引用的父表列是 PRIMARY KEY 或 UNIQUE KEY。
问题五:SQL_MODE 差异
升级到 8.4 后,部分历史 SQL 报错了。排查下来发现是 sql_mode 的默认行为有变化。
MySQL 8.4 在某些 SQL 模式的默认值上与 8.0 存在差异,尤其是 ONLY_FULL_GROUP_BY 的严格程度。如果应用代码中存在 SELECT 查询包含不在 GROUP BY 子句中的非聚合列,升级后这些查询会直接报错。
建议升级前先在测试环境中将 sql_mode 设置为与 8.4 默认值一致,跑一遍完整的回归测试。发现问题的 SQL 要修改而不是降低严格模式。
升级后的验证
升级完成不代表工作结束。建议做以下几件事:
- 查看错误日志:
tail -n 100 /var/log/mysqld.log,确认没有异常报错 - 检查慢查询:对比升级前后的慢查询数量和分布
- 验证复制状态:如果有主从架构,确认
SHOW REPLICA STATUS\G一切正常 - 业务流量灰度切换:先切一部分流量,观察至少一到两个完整的业务周期
总结
从 8.0.28 到 8.4.7 的升级,实际涉及认证机制、字符集、数据类型、外键约束、SQL 模式等多个维度的兼容性调整。
