mysql 8.0升级后权限表真损坏(如mysql.user不存在或innodb页损坏)只能用--initialize-insecure重建系统库,不可用已移除的mysql_upgrade或不支持的repair table;需先停服务、备份并移走mysql目录,再初始化,登录后立即重设root密码并补全权限,特别注意mysql.infoschema@localhost用户必须存在且host为localhost。

MySQL 8.0 升级后权限表损坏,不能靠 mysql_upgrade 修复——它在 8.0.16+ 已被彻底移除;也不能用 REPAIR TABLE mysql.user,InnoDB 不支持该操作;更不能手动 INSERT INTO mysql.user 硬写,字段语义、类型、默认值稍有偏差就会导致启动失败或认证崩溃。唯一安全路径是重建系统库。
确认是不是真损坏,而不是 plugin 或 authentication_string 异常
很多“权限表损坏”其实是字段值错乱,不是物理损坏:
- 停服务后加
--skip-grant-tables --skip-networking启动:mysqld --skip-grant-tables --skip-networking --datadir=/var/lib/mysql - 能进 MySQL 就说明表结构还在;执行
SELECT User, Host, plugin, authentication_string FROM mysql.user WHERE User = 'root'; - 如果返回结果但
plugin是空、auth_socket或caching_sha2_password,且客户端不兼容,那就不是损坏,是认证配置问题 - 只有出现
Table 'mysql.user' doesn't exist、Incorrect information in file: './mysql/user.frm'或日志里明确报InnoDB: Database page corruption,才属于真损坏
MySQL 8.0+ 权限表损坏必须用 --initialize-insecure 重建
InnoDB 系统库无法在线修复,--initialize-insecure 是唯一受控重建方式:
- 彻底停掉 mysqld:
systemctl stop mysqld,再killall mysqld确保无残留进程 - 备份整个
/var/lib/mysql(保留ibdata1、ib_logfile*),只重命名或移走mysql/子目录:mv /var/lib/mysql/mysql /var/lib/mysql/mysql.bak - 用同版本
mysqld初始化:mysqld --initialize-insecure --datadir=/var/lib/mysql --user=mysql - 启动服务:
systemctl start mysqld;此时root@localhost密码为空,立刻登录并重设:mysql -u root -p(回车),再执行ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass';
重建后必须补全用户权限,不能直接还原旧 mysqldump
旧版 mysqldump --all-databases 备份会因字段缺失(如 Password)、类型不匹配(Select_priv 从 'Y' 变为 TINYINT(1))导致静默失败:
- 升级前若留有
user_grants.sql(由SHOW GRANTS导出),现在可直接重放:mysql -u root -p - 没有备份?只能从旧实例或备份中重新导出逻辑权限:
mysql -u root -p -e "SELECT CONCAT('SHOW GRANTS FOR ''',User,'''@''',Host,''';') FROM mysql.user WHERE User NOT IN ('mysql.infoschema','mysql.session','mysql.sys')" | mysql -u root -p --skip-column-names | sed 's/$/;/g' > user_grants.sql - 重放后务必执行
FLUSH PRIVILEGES;——否则权限不会加载到内存 - 特别注意
mysql.infoschema@localhost用户:若SHOW DATABASES报ERROR 1449,需手动创建并授SELECT ON information_schema.*和SELECT ON performance_schema.*
重建系统库后最易忽略的一点:mysql.infoschema 用户必须存在且 host 严格为 'localhost',哪怕你只用 root;否则所有元数据查询(包括 SHOW TABLES)都会失败,而错误提示根本不会指向这个账户。











