mysql 8.0.16起mysql_upgrade已被彻底废弃,所有升级由mysqld启动时自动完成,分数据字典升级和服务器对象升级两步,通过--upgrade选项控制行为。

mysql_upgrade 在 MySQL 8.0 中已彻底废弃,执行它不会修复任何问题,反而可能引发元数据冲突或不可逆的字典损坏。
mysql_upgrade 命令直接报错或静默失败
MySQL 8.0.16 起官方正式移除了 mysql_upgrade 工具。如果你在终端输入该命令:
- 返回
command not found:说明二进制包里根本没这个文件; - 返回空输出或提示 “This installation of MySQL is already upgraded”:实际只是跳过,并未校验系统表结构;
- 若强行从旧版本拷贝该工具运行:极大概率触发
Failed to open mysql.component table或Data Dictionary initialization failed类错误。
这不是权限或路径问题,是内核层面移除——MySQL 8.0 启动时会自动完成数据字典升级,无需人工干预。
升级后表空间/系统表异常的真实原因
你看到的 mysql.user 字段缺失、performance_schema 视图报错、SHOW GRANTS 返回空,不是因为“忘了跑 upgrade”,而是系统库结构未适配新版本。常见诱因包括:
- 升级时未清空或替换旧的
/var/lib/mysql/mysql/目录(尤其是.ibd和.sdi文件残留); - 使用
--skip-grant-tables启动后误删/清空了mysql库; - 从 MySQL 5.7 直接拷贝
ibdata1+ib_logfile*迁移,但没重建数据字典; - 某些云厂商镜像预装了不兼容的初始化脚本,覆盖了 8.0 正确的首次启动逻辑。
这些情况,mysql_upgrade 既不能识别,也无法修复。
真正该做的三件事(按优先级)
-
停服务后,用同版本干净实例导出
mysql库结构
启动一个全新、未初始化的 MySQL 8.0 实例(mysqld --initialize-insecure --datadir=/tmp/clean),然后:mysqldump --no-data --skip-triggers --skip-routines mysql > mysql_struct.sql
再停掉故障实例,用该 SQL 替换原/var/lib/mysql/mysql/下的表定义(注意保留ibdata1和日志文件)。 -
若无干净环境,才考虑
--initialize-insecure(但必须满足三个前提)-
ps aux | grep mysqld确认无残留进程; - 原
/var/lib/mysql/mysql/已重命名备份(如mysql_bak_20260508); -
my.cnf中已注释掉innodb_force_recovery。
-
别碰
ibdata1或手动改.sdi文件
这类操作在 MySQL 8.0 数据字典模式下等同于直接破坏事务系统——恢复后可能出现 GTID 断裂、复制中断、甚至无法启动。
修复最常被忽略的一点:MySQL 8.0 的“自动升级”只发生在首次正常启动时。如果之前因报错反复启停、或长期挂着 innodb_force_recovery=1,它就再也不会触发内部升级逻辑。此时必须清掉旧系统库,让服务真正“第一次”启动。











