mysql 8.0升级后权限异常的核心原因是mysql.user表结构变更(移除password字段、新增authentication_string、默认plugin切换为caching_sha2_password)及权限语义收紧,导致旧数据无法兼容新表结构;必须成功执行升级后版本的mysql_upgrade,否则grant报错、show grants为空、select * from mysql.user提示“unknown column 'password'”等问题必然出现。

MySQL 8.0升级后权限结构变化引发的报错,核心原因是 mysql.user 表字段被精简、认证插件默认切换、权限语义逻辑收紧——不是配置没生效,而是旧数据根本“装不进”新表结构里。
mysql_upgrade 没跑或跑失败,权限表元数据不匹配
升级后首次登录能进,但执行 GRANT 报错、SHOW GRANTS 显示为空、甚至 SELECT * FROM mysql.user 提示 “Unknown column 'Password'”,基本可断定 mysql_upgrade 没成功运行。
- 必须用升级后的二进制执行:
/usr/local/mysql-8.0/bin/mysql_upgrade,不能依赖 PATH 里的旧版 - 执行前确保无活跃业务连接:
SHOW PROCESSLIST;,重点杀掉非system user的连接 - 加
--verbose --force并重定向日志:mysql_upgrade --verbose --force > upgrade.log 2>&1,出错后直接搜最后一段ERROR - 若卡在
mysql.innodb_index_stats或提示Table doesn't exist,说明底层系统表未就绪,需先确认mysqld启动时加了--upgrade=FORCE
用户登录成功但权限不生效,plugin 和 authentication_string 不对
能 mysql -u root -p 登录,但应用连不上或执行 SQL 报 Access denied,大概率是认证插件或凭证字段没更新到位。
- 查当前状态:
SELECT User, Host, plugin, authentication_string FROM mysql.user WHERE User = 'root'; - 若
plugin是空值或caching_sha2_password,而客户端不支持,就执行:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 若
authentication_string为空,说明mysql_upgrade没写入凭证,不能直接 UPDATE 字段,应重置密码:ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass'; - 别信
FLUSH PRIVILEGES能修好一切——它只重载内存权限缓存,不修复表结构或凭证缺失
GRANT 报错 error 1410:create user 和 grant 必须拆开
执行类似 GRANT ALL ON *.* TO 'u'@'%' IDENTIFIED BY 'p'; 直接报 ERROR 1410 (42000),这是 MySQL 8.0 强制拆分用户创建与授权的语法限制,不是权限不足。
- 必须分两步:
CREATE USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p';,再GRANT ALL ON *.* TO 'u'@'%'; - 若旧库用户用的是
sha256_password或其他插件,建用户时要显式指定:IDENTIFIED WITH sha256_password BY 'p' - 远程访问需额外处理 host:
UPDATE mysql.user SET Host = '%' WHERE User = 'u' AND Host = 'localhost'; FLUSH PRIVILEGES;(注意:生产环境慎用%) - 批量迁移用户时,禁用
NO_AUTO_CREATE_USER模式——该模式在 8.0 已移除,脚本里有就删掉
权限脚本导入失败,字段数/类型/默认值不兼容
用 mysqldump mysql 导出再导入新实例,报列数不匹配、主键冲突或 Invalid default value,是因为 8.0 权限表新增字段(如 password_required)、移除了字段(如 Password),且部分字段类型变严格。
- 禁止 dump 整个
mysql库——只导出关键权限表:mysqldump --no-create-info --where="User != 'mysql.infoschema'" mysql user db tables_priv columns_priv - 导入前清空目标库权限表:
TRUNCATE mysql.user; TRUNCATE mysql.db;,否则唯一键冲突 -
mysql.db.Db字段在 8.0 后区分大小写,若旧库有DB_NAME,新库lower_case_table_names=1会导致权限不生效,需统一配置或改名 - 别用
PASSWORD('xxx')插入密码——8.0 不识别该函数,直接写authentication_string值(从已有用户查:SELECT authentication_string FROM mysql.user LIMIT 1;)
最易被忽略的一点:权限问题从来不是单点故障。它往往是 mysql_upgrade 失败 + 认证插件不匹配 + 用户创建语法错误 三者叠加的结果。排查时别只盯一个报错,得顺着登录链路一层层验:能否连上 → 连上后查 user 表结构 → 查具体用户的 plugin 和 authentication_string → 再试 GRANT 语句是否语法合规。











