根本原因是客户端不支持caching_sha2_password插件要求的rsa公钥交换或tls加密,导致握手失败;解决方法是执行alter user 'user'@'host' identified with mysql_native_password by 'pwd'并立即flush privileges。

caching_sha2_password 连接失败,不是密码错了,也不是网络不通,而是客户端压根不认这个插件——握手直接中断。最稳的解法是改用户认证方式,不是调配置、不是换驱动(除非你真想长期用新协议)。
怎么确认真是 caching_sha2_password 在报错
别猜,先登录 MySQL 命令行(比如 mysql -u root -p),执行:
SELECT user, host, plugin FROM mysql.user WHERE user = 'your_user';
重点看 plugin 列值。如果显示 caching_sha2_password,且你用的是以下任一环境,基本坐实问题:
- Navicat 15 以下版本(尤其 12–14)
- PyMySQL
- PHP mysqli 扩展 ≤ 7.4(宝塔/AMPPS 默认包常见)
- JDBC Connector/J
- Django
注意:'root'@'localhost'、'root'@'127.0.0.1'、'root'@'%' 是三个独立账号,必须分别查、分别处理。
ALTER USER 改插件必须带密码、匹配 host、立刻 FLUSH PRIVILEGES
这是见效最快的操作,但漏掉任意一条都会白忙活甚至锁死账户:
安全的随机密码生成器。支持自定义长度、字符类型(大写/小写字母、数字、特殊符号),排除相似字符,批量生成。纯 Python 标准库,无需 API 密钥。
- 必须显式重设密码:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MyPass123!';—— 只写IDENTIFIED WITH mysql_native_password不带BY,原密码会被清空 - host 必须完全匹配:Navicat 默认走 TCP,即
'root'@'127.0.0.1',不是localhost;Docker 内连宿主机可能是'appuser'@'172.17.0.1' - 执行后必须立刻跟
FLUSH PRIVILEGES;:MySQL 8.0.16+ 权限缓存更严格,不刷就不生效 - 云数据库(如阿里云 RDS)通常禁写配置文件,
ALTER USER是唯一可行路径
改完服务端,Navicat / JDBC / PyMySQL 还连不上?检查客户端侧缓存和参数
服务端改完了,客户端未必“收到通知”:
- Navicat 会缓存旧连接配置:必须关掉软件重开,或删掉旧连接、新建一个——它不会自动重协商认证插件
- JDBC URL 需加参数(仅限内网可信环境):
?allowPublicKeyRetrieval=true&useSSL=false,且驱动版本 ≥ 8.0.16 - PyMySQL ≥ 1.0.2 才原生支持
caching_sha2_password;旧版要么升级,要么换mysql-connector-python - 密码含
@或/会被 URL 解析吃掉:Navicat 连接里填密码时,建议先 URL 编码,或改用mysql_native_password规避
default_authentication_plugin 配置项只管新用户,对老账号无效
在 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf 里加:
[mysqld] default_authentication_plugin = mysql_native_password
重启 MySQL 后,只影响后续 CREATE USER 的新账号,对已存在的 root、admin 等完全没用。Docker 启动加 --default-authentication-plugin=mysql_native_password 同理。很多人改完就以为搞定,结果 SELECT ... FROM mysql.user 一看,plugin 字段还是 caching_sha2_password。
localhost 却没同步处理 'root'@'localhost',或者 Navicat 连接字符串里 host 是 127.0.0.1 却只改了 'root'@'localhost'。










