根本原因是新版本拒绝加载结构不匹配的系统表,如mysql.user字段缺失、类型错位或默认值非法;mysqld --upgrade仅处理可识别的迁移状态,对已固化旧格式或字段定义破坏无能为力;mysql_upgrade在8.0.16+已废弃且依赖正常连接,无法修复认证失败场景下的元数据损坏;实操应停服务、备份旧mysql目录、用--initialize-insecure重建系统库,再重置root密码。

MySQL升级后服务启动失败,根本原因不是“权限表旧”,而是新版本拒绝加载结构不匹配的系统表——尤其是 mysql.user 等表字段缺失、类型错位或默认值非法(如 password_last_changed 字段设了 0000-00-00 00:00:00 这种在 8.0+ 不被接受的值)。硬启动会卡在数据字典初始化阶段,直接报 ERROR 1067 (42000): Invalid default value for 'password_last_changed' 或 MY-013183: Data Dictionary initialization failed。
为什么 mysqld --upgrade 不自动修复旧权限表?
MySQL 8.0.16+ 启动时确实会尝试自动升级系统表,但前提是:旧表结构必须能被识别为“可迁移状态”。如果原库是 5.6 直升 8.0,或 mysql 库被手动导出/导入过(比如用 mysqldump --all-databases 导出再导入),表结构就已固化为旧格式,mysqld --upgrade 会跳过这些“看似完整实则错配”的表,不报错也不修复。它只处理真正缺失字段或索引的场景,对字段类型/默认值冲突无感。
为什么 mysql_upgrade 工具也失效?
mysql_upgrade 在 8.0.16+ 已被标记为废弃,且它本身依赖一个能正常连接的 MySQL 实例。若权限表损坏导致 root@localhost 都无法认证登录,mysql_upgrade 根本连不上,直接报 Access denied 并退出。更关键的是:它不会重建表结构,只做字段补全和索引同步——对已被破坏的字段定义(如 Password 列残留、authentication_string 为空)无能为力。
跳过权限表重建的实操路径
当确认数据目录中业务库(如 your_db)文件完好,仅 mysql 系统库损坏时,应放弃修复,直接重建:
- 停掉 MySQL:
systemctl stop mysqld(Linux)或net stop MySQL80(Windows) - 备份旧
mysql目录(可选但强烈建议):mv /var/lib/mysql/mysql /var/lib/mysql/mysql.bak - 用初始化命令生成全新系统库:
mysqld --initialize-insecure --datadir=/var/lib/mysql --user=mysql(路径按实际调整) - 启动服务:
systemctl start mysqld,此时mysql库是 8.0 原生结构,含authentication_string、account_locked等字段 - 立即登录并重置 root 密码:
mysql -u root -p(空密码回车),执行ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_strong_password';
注意:这个操作不碰任何业务库文件,只替换权限元数据。但务必确认你没把业务库误放在 mysql 目录下——那是致命错误。











