必须按5.7→8.0路径升级,升级前须运行util.checkforserverupgrade()做兼容性检查并备份,否则易启动失败或数据不可用;该检查涵盖no_auto_create_user、myisam表、关键字命名冲突等20+项,error必须修复,warning中utf8mb4变更需关注应用层emoji存储;my.cnf需手动调整sql_mode、default_authentication_plugin和字符集参数;推荐dump/restore方式提升稳定性,云厂商升级本质是dump/restore+切流。

不能直接跳着升,必须走 5.7 → 8.0 的路径,且升级前必须做兼容性检查和备份,否则大概率卡在启动或数据不可用。
升级前必须跑 util.checkForServerUpgrade()
这个检查不是可选项,是唯一能提前暴露问题的手段。MySQL Shell 的 util.checkForServerUpgrade() 会扫描 20+ 项,包括:NO_AUTO_CREATE_USER 是否还在 sql_mode 里、有没有用 MyISAM 系统表、是否存在 MySQL 8.0 关键字命名的库/表/存储过程(比如叫 rank 或 json 的表)、RocksDB 分区表是否混用等。
常见错误现象:
- 检查报告里出现
ERROR级别条目,不修复就强行升级,mysqld启动失败,报错类似Failed to initialize DD tables - 警告(
WARNING)可以先不处理,但其中涉及utf8mb4默认字符集变更的,应用层可能存 emoji 失败
实操建议:
将音频或视频文件转录为带时间轴的歌词或字幕格式(如LRC、SRT、WebVTT、ASS、TTML),并制作卡拉OK视频。
- 下载对应目标版本的 MySQL Shell(比如升 8.0.34 就用 8.0.34 的 shell),不要用 5.7 自带的
- 命令要带 socket 路径,避免连错实例:
./mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()" - 输出日志里所有
ERROR必须逐条解决,比如删掉NO_AUTO_CREATE_USER、把MyISAM表转成InnoDB、重命名冲突对象
my.cnf 配置必须手动调整几处关键参数
MySQL 8.0 启动时会校验配置项,很多 5.7 兼容但 8.0 已废弃的参数会导致服务起不来。最常踩坑的是 sql_mode、认证插件、字符集三类。
容易被忽略的点:
-
sql_mode中若含NO_AUTO_CREATE_USER,启动直接报错退出;8.0 默认值已移除它,但如果你的配置文件里还显式写了,就必须删掉 -
default_authentication_plugin=mysql_native_password建议显式加上——否则新用户默认用caching_sha2_password,老应用连接会报Client does not support authentication protocol -
character_set_server和collation_server若仍设为latin1,虽能启动,但新建库表默认变utf8mb4,混合字符集极易引发乱码或索引失效
实操建议:
- 保留原
my.cnf大部分内容,只改这三项,其他如innodb_buffer_pool_size等不用动 - 不要盲目加
skip-grant-tables绕过权限检查,升级失败后更难恢复 - 升级后首次启动时加
--log-error-verbosity=3查看详细报错位置
升级方式选 in-place 还是 dump/restore?
in-place 升级(停服、换二进制、启新版本)快但风险集中;dump/restore(导出 SQL 再导入)慢但可控,适合对稳定性要求极高的场景。
性能与兼容性影响:
- in-place 升级后,
mysql系统库会自动执行mysql_upgrade(8.0.16+ 版本由mysqld内置完成),但仅限于系统表结构变更,业务数据不校验一致性 - dump/restore 方式下,
mysqldump --all-databases --set-gtid-purged=OFF是安全起点;但大库(>50GB)导入耗时长,期间业务中断时间不可控 - 云厂商控制台升级(如阿里云 RDS)本质是 dump/restore + 切流,对业务无感,但不支持本地盘单节点实例
实操建议:
- 生产环境数据量
- 无论哪种方式,
mysqldump导出时务必加--skip-triggers和--skip-routines单独处理,避免触发器中调用 5.7 特有函数导致导入失败 - 升级后第一件事:连上去执行
SELECT VERSION(), @@sql_mode;确认版本和模式已生效
升级后最容易被忽略的三件事
很多人以为服务起来就完事了,其实真正的坑在后面:应用连得上、查得出来、写得进去,不代表逻辑正确。
关键盲区:
-
JSON字段行为变化:5.7 的JSON_EXTRACT返回带引号字符串,8.0 返回原生类型;如果应用层用==比较 JSON 值,可能从 true 变 false -
GROUP BY语义收紧:8.0 默认启用ONLY_FULL_GROUP_BY,原来能跑的 SQL 如果SELECT列没全在GROUP BY里,直接报错 - 密码策略升级:新创建用户默认强制 SHA256 加密,老应用若硬编码了
mysql_native_password插件名,连接会拒绝
实操建议:
- 上线前用慢查询日志 +
pt-query-digest抽样比对 5.7 和 8.0 下相同 SQL 的执行计划差异 - 把所有
SELECT语句过一遍,确认GROUP BY是否合规;临时绕过可用SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));,但别长期依赖 - 测试环境必须用真实流量镜像,不能只靠单元测试——窗口函数、CTE、Hash Join 这些特性在 ORM 层可能触发隐式降级










