MySQL 8.0.16起mysql_upgrade已被彻底移除,执行会报command not found或引发元数据冲突;系统表必须为InnoDB引擎且plugin字段需匹配认证插件,修复需通过mysqld启动时自动升级或--upgrade=FORCE强制触发。

系统表迁移失败不是配置没配对,而是 MySQL 8.0 启动时没能完成自动升级流程——常见于直接拷贝数据目录、跳过权限启动后误操作、或残留 mysql_upgrade 脚本干扰。修复核心是让服务以可控方式触发一次真正的内部升级。
为什么 mysql_upgrade 会报错或无效
MySQL 8.0.16 起该命令已被彻底移除。执行它只会返回 command not found,或在旧脚本里强行调用导致 mysql.user 字段错乱(比如缺失 plugin 列)、performance_schema 视图不可用。真正起作用的是 mysqld 自身的启动时升级逻辑,它只在首次用新二进制启动旧数据目录时运行一次,且不可重复触发。
- 错误日志出现
[MY-010929] Storage engine 'MyISAM' does not support system tables,说明mysql.db、mysql.user等仍是 MyISAM 引擎——8.0 要求全部为 InnoDB - 执行
SELECT * FROM mysql.user报Unknown column 'password_last_changed',代表表结构未更新,字段缺失 - 连得上但
SHOW GRANTS返回空,大概率是mysql.role_edges或mysql.proxies_priv表引擎或结构异常
用 --upgrade=FORCE 手动触发系统表升级
当 mysqld 启动卡住、拒绝加载系统库,或日志提示“data dictionary initialization failed”时,需强制进入升级模式。这不是重装,而是让服务器重新走一遍元数据校验与转换流程。
- 确认
mysqld进程已完全退出:ps aux | grep mysqld无残留 - 临时注释掉配置文件中可能存在的
innodb_force_recovery(否则升级会被跳过) - 执行:
mysqld --user=mysql --datadir=/var/lib/mysql --upgrade=FORCE - 观察错误日志,成功时会出现类似
Upgrading system tables...和Finished upgrading system tables的记录 - 完成后立即停止进程,再用正常方式启动:
systemctl start mysqld
系统表引擎残留 MyISAM 怎么修
如果 --upgrade=FORCE 后仍报 MyISAM 错误,说明部分系统表被手动改过或备份恢复时带入了旧引擎。不能直接 DROP TABLE 或 TRUNCATE,必须在跳过权限模式下修复。
- 停服务:
systemctl stop mysqld - 跳过权限启动:
mysqld_safe --skip-grant-tables --skip-networking & - 登录后逐个转引擎:
USE mysql; ALTER TABLE db ENGINE=InnoDB; ALTER TABLE user ENGINE=InnoDB; ALTER TABLE columns_priv ENGINE=InnoDB;(注意:必须覆盖所有系统表,SHOW TABLE STATUS IN mysql查出 Engine 不是InnoDB的都要改) - 刷新权限:
FLUSH PRIVILEGES;(即使提示 warning 也要执行) - 杀掉后台进程:
pkill mysqld,再正常启动
修复后必须验证的三件事
表面能连、能查不等于系统表真正就绪。最容易忽略的是认证插件和字段完整性,它们直接影响后续用户管理。
- 检查
mysql.user是否含plugin列:DESCRIBE mysql.user;—— 若无,说明升级未生效,得重跑--upgrade=FORCE - 确认 root 用户插件是
caching_sha2_password或mysql_native_password:SELECT User, Host, plugin FROM mysql.user WHERE User='root'; - 验证权限是否可读:
SHOW GRANTS FOR 'root'@'localhost';—— 返回空或报错,说明role_edges、default_roles等新表仍异常


















