答案是客户端与服务器认证协议不兼容:MySQL 8.0默认用caching_sha2_password,而Navicat 12、PHP 7.x mysqli等旧客户端仅支持mysql_native_password,导致握手阶段失败;需执行SELECT User,Host,plugin FROM mysql.user WHERE User='your_username'确认插件,再用ALTER USER切换并FLUSH PRIVILEGES。

不是权限配置错了,是客户端和服务器在“握手”阶段就卡在认证协议上——MySQL 8.0 默认用 caching_sha2_password,而你的老客户端(比如 Navicat 12、PHP 7.x 的 mysqli、Node.js 的 mysql 包)只认 mysql_native_password。
怎么确认真是认证协议问题
别急着改配置,先验证错误是否真源于此。连接失败时,典型报错是:ER_NOT_SUPPORTED_AUTH_MODE 或 Client does not support authentication protocol requested by server。
用 root 登录 MySQL 后执行:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'your_username';
如果返回的 plugin 是 caching_sha2_password,而你用的是上述旧客户端,那基本就是它了。
注意:SHOW GRANTS 能查出来 ≠ 认证成功——权限语句能读,但连接根本进不来。
ALTER USER 切换插件是最快见效的方法
这是无需重启服务、最快验证的修复方式,适合开发/测试环境快速通路:
- 执行
ALTER USER 'your_username'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 务必跟一句
FLUSH PRIVILEGES;,否则内存缓存不更新,新设置不生效 - 若需远程连接,把
'localhost'换成'%'或具体 IP,如'192.168.1.100' - 该操作只影响指定用户,不影响其他用户或全局默认设置
为什么不能直接 UPDATE mysql.user 表
MySQL 8.0 禁止直接修改系统表字段,尤其是 plugin 和 authentication_string:
- 执行
UPDATE mysql.user SET plugin = 'mysql_native_password' WHERE User = 'root';会报错ERROR 1396 (HY000)或提示 “Table is read only” - 系统表受严格保护,
ALTER USER是唯一安全、兼容且被 MySQL 官方支持的修改方式 - 直接写表还可能破坏哈希格式一致性,导致后续密码校验逻辑异常
容易被忽略的底层前提:mysql_upgrade 必须跑成功
如果升级后没运行或没跑完 mysql_upgrade,mysql.user 表结构可能仍缺 plugin 字段,此时即使执行 ALTER USER 也会静默失败或字段写不进去。
检查方法:
DESCRIBE mysql.user;
确认输出里有 plugin 和 authentication_string 字段;如果没有,必须先用升级后的二进制运行:
/usr/local/mysql-8.0/bin/mysql_upgrade --verbose --force
再重试 ALTER USER —— 很多人卡在这一步,却反复折腾客户端配置。


















