mysql_upgrade升级前必须停应用连接,因其会修改系统库;须用新版本对应二进制执行;失败时应查日志而非重试;8.0.16+虽弃用该命令但仍需手动触发--upgrade=FORCE完成兼容性修复。

运行 mysql_upgrade 前必须停掉应用连接
升级 MySQL 版本后,mysql_upgrade 不是“点一下就完事”的工具——它会直接修改系统库(比如 mysql 库里的表结构),如果此时有应用正在连着数据库读写,轻则报错中断,重则导致元数据损坏或锁死。
实操建议:
- 确认所有业务连接已断开:查
SHOW PROCESSLIST,重点关注User非root或system user的活跃连接 - 临时停用应用服务,或把数据库设为只读:
SET GLOBAL read_only = ON(注意:这不能阻止 super 用户写入) - 别在生产环境边跑边升——哪怕只是测试,也要模拟真实连接压力,否则容易漏掉并发冲突问题
mysql_upgrade 必须用升级后的 mysqld 对应版本执行
常见错误现象是:MySQL 从 5.7 升到 8.0 后,仍用旧版 mysql_upgrade(比如系统 PATH 里残留的 5.7 二进制)去跑,结果提示 Unknown table 'performance_schema.session_variables' 或直接跳过关键校验。
原因很简单:不同版本的 mysql_upgrade 内置了对应版本的检查逻辑和 SQL 补丁。8.0 的升级脚本要处理 data_dictionary 表、角色权限模型等 5.7 没有的东西。
实操建议:
- 明确指定路径运行,比如
/usr/local/mysql-8.0/bin/mysql_upgrade,而不是只敲mysql_upgrade - 用
which mysql_upgrade和mysql_upgrade --version双重核对版本 - 如果用的是 Docker,确保容器内执行的是镜像自带的二进制,不是宿主机挂载进来的旧版
升级失败时别急着重试,先看 mysql_upgrade 的真实退出码和日志
很多人看到报错就立刻再跑一遍 mysql_upgrade,结果把半截失败的状态反复叠加,最后连 mysql 库都打不开。其实 mysql_upgrade 失败时多数会输出具体 SQL 错误,比如 ERROR 1878 (HY000) at line 1: Failed to create the column statistics,这往往指向底层存储引擎不兼容或权限不足。
实操建议:
- 加
--verbose参数重跑一次,把完整输出重定向到文件:mysql_upgrade --verbose --force > upgrade.log 2>&1 - 重点检查最后一段 ERROR 行,以及是否卡在某个特定表(如
mysql.innodb_index_stats) - 若提示权限错误,确认运行用户对
mysql库所有表有SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX权限,不只是root@localhost,还要看 host 是否匹配(比如root@127.0.0.1是另一个账号)
8.0+ 版本中 mysql_upgrade 已被弃用,但实际仍需手动触发兼容性修复
MySQL 官方文档说 8.0.16+ “不再需要 mysql_upgrade”,这是指自动检测 + 自动执行逻辑被移除了,不是说兼容性检查不存在了。真实情况是:升级后首次启动 mysqld 会自动检查系统表,发现不一致就拒绝启动,并提示你手动运行 mysqld --upgrade=FORCE ——这个动作本质就是 mysql_upgrade 的内核逻辑。
所以别信“升级完直接 start 就行”。尤其从 5.7 升 8.0,mysql.user 表字段、密码认证插件、默认字符集都变了,不走一遍升级流程,后续连 CREATE USER 都可能报错。
实操建议:
- 升级后首次启动前,先执行:
mysqld --upgrade=FORCE --basedir=/path/to/8.0 --datadir=/var/lib/mysql - 如果用 systemd,改
mysqld.service的ExecStart加上--upgrade=FORCE,否则 systemctl start 会卡住并静默失败 - 升级完成后务必验证:
SELECT VERSION(), @@sql_mode;看是否真加载了新默认值,而不仅是进程起来了










