MySQL 8.0已弃用mysql_upgrade,系统表引擎转换需通过mysqld --upgrade=FORCE强制触发,失败主因是权限不足、残留.frm文件或磁盘空间不够。

MySQL 8.0 彻底移除了对 MyISAM 系统表的支持,升级后若看到 [MY-010929] Storage engine 'MyISAM' does not support system tables 这类报错,说明 mysql.user、mysql.db 等核心系统表仍为 MyISAM 引擎——这不是配置错误,而是升级流程卡在了自动转换环节。
为什么 mysql_upgrade 不起作用?
从 MySQL 8.0.16 起,mysql_upgrade 已被弃用。它不再是一个独立工具,所有系统表升级逻辑已内建到 mysqld 启动流程中。如果你还执行 mysql_upgrade,只会收到“客户端已弃用”的提示,且无法触发真正的引擎转换。
- 真正生效的是服务器启动时的自动升级机制,依赖
--upgrade参数控制 - 旧数据目录首次用 8.0+ 二进制启动时,会自动尝试将 MyISAM 系统表转为 InnoDB,但可能因权限、锁或元数据不一致而静默失败
-
mysql_upgrade在 8.0.44 下运行甚至可能报ERROR 1726: Storage engine 'InnoDB' does not support system,因为此时系统表状态已混乱
如何强制完成 MyISAM → InnoDB 的系统表转换?
必须绕过默认启动逻辑,用 --upgrade=FORCE 显式触发完整校验与转换。这不是“重试”,而是让服务器重新走一遍初始化路径。
- 先确保 MySQL 已停止:
sudo systemctl stop mysql(或对应服务名) - 用绝对路径调用新版本
mysqld,显式指定 datadir 和 upgrade 模式:mysqld --user=mysql --datadir=/var/lib/mysql --upgrade=FORCE - 观察日志输出 —— 成功时会出现类似
Upgrading system tables for new version...和mysql.user table upgraded to InnoDB的明确记录 - 不要加
&后台运行;等进程自然退出(通常 10–30 秒),再用常规方式启动服务
转换失败时最该检查的三件事
自动升级失败往往不报错,只留警告。关键要看日志里有没有 Failed to upgrade table 或 Could not open mysql.db 类提示。
-
权限问题:运行
mysqld的用户(如mysql)必须对整个datadir有读写权限,且 SELinux 上需执行restorecon -R /var/lib/mysql -
残留 .frm 文件干扰:MySQL 8.0 已废弃
.frm元数据文件,但若升级前存在损坏或不匹配的mysql/*.frm,会导致解析失败;可临时备份后删掉/var/lib/mysql/mysql/*.frm(仅限系统库) -
磁盘空间不足:转换过程需临时写入新表结构,
ibdata1扩容或tmpdir空间不够都会中断流程;检查df -h /var/lib/mysql和df -h $(dirname $(mktemp -u))
应用层 MyISAM 表要不要一起转?
系统表必须转,业务表则要分情况。MyISAM 表本身在 8.0 中仍可用,但已不推荐:
- 全文索引行为不一致:
ALTER TABLE t1 ENGINE=InnoDB后必须重建全文索引,否则搜索失效 - 无事务、易崩溃:尤其在非正常关机后,MyISAM 表损坏概率远高于 InnoDB
- 主键缺失风险:MyISAM 允许无主键,但迁移到 InnoDB 前最好补上,避免隐式
row_id冲突 - 转换命令示例:
ALTER TABLE myisam_table ENGINE=InnoDB ROW_FORMAT=DYNAMIC;(注意:需确保innodb_file_per_table=ON)
真正容易被忽略的是:系统表转换失败后,mysql 库里的视图、存储过程定义可能已损坏,但不会立即暴露——直到你执行 CREATE USER 或 GRANT 才报错。别只盯着登录失败,升级后第一件事是查 SELECT COUNT(*) FROM mysql.user; 是否能正常返回结果。











