MySQL 8.0系统表必须用InnoDB,因其DDL原子性要求事务支持,而MyISAM不支持事务、无法回滚且崩溃状态不可预测;若系统表仍为MyISAM,mysqld启动即报阻断错误MY-010929并卡住。

MySQL 8.0系统表为什么必须用InnoDB
因为DDL语句在8.0中要求原子性,而MyISAM不支持事务、无法回滚、崩溃后状态不可预测——它根本无法满足数据字典与系统表同步变更的强一致性前提。
MyISAM系统表在8.0启动时会直接报错
只要mysql.user、mysql.db等系统表还是MyISAM引擎,mysqld就无法完成初始化。你看到的[MY-010929] Storage engine 'MyISAM' does not support system tables不是警告,是阻断性错误,服务会卡在启动阶段。
- 错误不会出现在客户端连接时,而是在
error.log里提前暴露,且通常伴随Failed to upgrade table或Could not open mysql.db - 即使你手动
ALTER TABLE mysql.user ENGINE=InnoDB,也会失败:系统表不允许直接DDL操作,必须走升级流程 -
mysql_upgrade命令在8.0.16+已彻底失效,执行它只会输出mysql_upgrade is deprecated,且对系统表无任何作用
--upgrade=FORCE是唯一可靠的修复入口
这不是“重试”,而是让mysqld绕过默认校验路径,强制重新加载并转换所有系统表结构。它会重建mysql库下所有表的元数据和存储格式,确保与8.0数据字典完全对齐。
- 必须用绝对路径调用新版本
mysqld,不能依赖service mysql start或systemctl——那些会跳过--upgrade参数 - 关键参数缺一不可:
--user=mysql --datadir=/var/lib/mysql --upgrade=FORCE;漏掉--user常导致权限不足静默失败 - 进程必须自然退出(不要
&后台运行),否则转换中途终止,后续再启可能进入更混乱的状态 - 成功标志是日志中出现
mysql.user table upgraded to InnoDB和Upgrading system tables for new version
转换失败最该盯住的三个底层条件
升级逻辑本身很健壮,但依赖外部环境。失败几乎总是这三件事之一没到位,而不是SQL语法或配置项问题。
-
SELinux或AppArmor限制了mysqld对/var/lib/mysql/mysql/的写权限,需运行restorecon -R /var/lib/mysql - 残留的
.frm文件干扰解析——MySQL 8.0已弃用该格式,但旧版遗留的/var/lib/mysql/mysql/*.frm会让升级器误判表结构,可临时移除(仅限mysql库) -
tmpdir或datadir所在分区空间不足,转换过程需要临时写入新表结构,df -h /var/lib/mysql和df -h $(dirname $(mktemp -u))必须都够用
mysqld进程退出即代表成功,此时必须用常规方式(如systemctl start mysql)重启服务——不要继续用--upgrade=FORCE启动生产实例,那会导致重复升级或锁表。


















