答案是执行select host, user, plugin from mysql.user where user = 'root'确认plugin字段值,若为caching_sha2_password或auth_socket即坐实问题;需对'root'@'localhost'、'root'@'127.0.0.1'等各host分别执行alter user...identified with mysql_native_password by 'pwd'并立即flush privileges。

这不是客户端版本太旧,而是服务端用户认证插件被意外改成了 caching_sha2_password
怎么确认是 plugin 导致的?
登录 MySQL(可用 mysql -u root -p --skip-password 跳过密码,或用 skip-grant-tables 启动)后执行:
SELECT host, user, plugin FROM mysql.user WHERE user = 'root';
如果看到 plugin 字段值是 caching_sha2_password 或 auth_socket,而不是 mysql_native_password,就坐实了问题根源。
- MySQL 5.7 默认仍用
mysql_native_password,caching_sha2_password是 8.0 的默认插件,但很多一键安装包、Docker 镜像或初始化脚本会提前启用它 -
auth_socket常见于 Ubuntu 系统自带的 MySQL 包,它跳过密码验证、依赖 Unix socket 文件权限,Navicat 等远程客户端根本无法适配 - 哪怕只改了一个账号(比如
root@localhost),只要 Navicat 连的是127.0.0.1或 IP,就会命中另一个未修复的账号记录
怎么安全地切回 mysql_native_password?
别直接 UPDATE 表——5.7 对 authentication_string 和 plugin 的耦合很敏感,手动更新容易导致空密码或静默登录失败。
- 优先用
ALTER USER:执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 如果提示 “ERROR 1396”,说明该账号不存在,先查准 host:
SELECT User, Host FROM mysql.user;,再按实际 host 执行(如'root'@'127.0.0.1'或'root'@'%') - 每改一个账号,必须跟一句
FLUSH PRIVILEGES;,否则内存缓存不更新,Navicat 还是连不上 - 改完立刻验证:
mysql -u root -p -h 127.0.0.1,模拟 Navicat 的连接方式,别只测localhost
为什么 GRANT 后还是报错?
因为 GRANT 不等于“立刻生效”——MySQL 5.7 的权限检查走的是内存缓存,而认证插件切换属于底层用户元数据变更,GRANT 完全不触发插件刷新。
- 常见误操作:先
GRANT ALL ON *.* TO 'dev'@'%';,再发现连不上,又去UPDATE mysql.user SET plugin='mysql_native_password'——这时plugin被设了,但authentication_string可能为空或格式不匹配,登录直接静默失败 - 更隐蔽的坑:用 Docker 启动时挂载了旧的
mysql数据库文件,里面已有caching_sha2_password用户记录,新容器启动后自动加载,你根本没动过任何命令 - Navicat 自带驱动较老,不支持
caching_sha2_password握手流程,错误信息里明确写 “Client does not support authentication protocol requested by server”,不是网络或权限问题
真正卡住人的地方,往往不是不会改插件,而是改完没刷缓存、连错了 host、或者压根没意识到自己连的是镜像里预置的用户记录。验证一定要用和客户端完全一致的连接参数,少一步都白忙。











