MySQL 8.0升级后权限“失效”90%非丢失而是结构不兼容:字段精简、plugin切换、authentication_string替代Password;应先用--skip-grant-tables确认是否认证插件不匹配(如caching_sha2_password),再通过SHOW GRANTS导出重放逻辑权限语句安全恢复。

MySQL 8.0 升级后用户权限“失效”,90% 的情况不是真丢了,而是旧数据装不进新表结构里——mysql.user 字段精简、plugin 默认切换、authentication_string 替代 Password,直接还原或硬写字段必然出错。必须绕开物理结构,走逻辑权限重建。
确认是权限丢失还是认证插件不兼容
先别急着重建系统库。很多“登不上”只是客户端不认 caching_sha2_password:
- 停服务后加
--skip-grant-tables启动:mysqld --skip-grant-tables --datadir=/var/lib/mysql - 执行
mysql -u root(不加-p)能进,说明表没损坏,只是认证卡住了 - 查当前配置:
SELECT User, Host, plugin, authentication_string FROM mysql.user WHERE User = 'root'; - 若
plugin是空、auth_socket或caching_sha2_password,且客户端报错ERROR 2059,就不是权限丢失,是插件不匹配
用 SHOW GRANTS 导出再重放是最安全的恢复方式
只要升级前还能登录任意一个高权限用户(哪怕只读),就能导出逻辑权限语句,完全避开字段差异:
- 在旧实例或备份中执行:
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 - 在新实例中导入:
mysql -u root -p - 导入后**必须立刻执行**:
FLUSH PRIVILEGES;——否则权限不会加载到内存 - 注意:MySQL 8.0+ 中
FILE、SHUTDOWN等动态权限需显式授予,不能靠旧备份自动带过来
mysql.infoschema@localhost 缺失导致 ERROR 1449
执行 SHOW DATABASES 报 ERROR 1449 (HY000): The user specified as a definer ('mysql.infoschema'@'localhost') does not exist,说明系统级账户损坏,不是普通用户问题:
- 先确认
mysql.user引擎是InnoDB:SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user';,若是MyISAM,执行ALTER TABLE mysql.user ENGINE = InnoDB; - 创建缺失用户:
CREATE USER 'mysql.infoschema'@'localhost' IDENTIFIED WITH mysql_native_password; - 只授必要权限:
GRANT SELECT ON information_schema.* TO 'mysql.infoschema'@'localhost';和GRANT SELECT ON performance_schema.* TO 'mysql.infoschema'@'localhost'; -
FLUSH PRIVILEGES;后验证是否生效
真损坏(如 Table 'mysql.user' doesn't exist)只能重建系统库
出现 Table 'mysql.user' doesn't exist 或日志报 InnoDB: Database page corruption,说明物理损坏,mysql_upgrade 和 REPAIR TABLE 都无效:
- 彻底停服务:
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 - 启动后立即用空密码登录:
mysql -u root -p(回车),然后执行:ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass'; - 重建后必须补全用户权限——不能直接还原旧
mysqldump --all-databases,字段类型和默认值已变,会静默失败
最常被忽略的一点:MySQL 8.0 的权限变更不是“改个配置就能回滚”的事,plugin、authentication_string、mysql.infoschema 这三者任何一个没对齐,都会让权限看起来“失效”。修复时得按角色分层处理——系统账户、认证方式、逻辑权限,不能混在一起试错。


















