根本原因是MySQL 8.0+默认认证插件caching_sha2_password与旧客户端协议不兼容;应执行ALTER USER 'user'@'host' IDENTIFIED WITH mysql_native_password BY 'pwd'并FLUSH PRIVILEGES。

这是客户端不支持 MySQL 8.0+ 默认认证协议导致的连接失败,不是密码错、网络通但连不上——本质是“双方说不同方言”
为什么 ALTER USER 不生效?host 和 plugin 必须显式指定
很多人执行 ALTER USER 'root' IDENTIFIED BY 'xxx' 后仍报错,因为这条命令只改密码,不碰认证插件,plugin 仍为 caching_sha2_password。真正生效的写法必须带完整 host 和 WITH 子句:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';- host 必须和你实际连接时一致:
localhost≠127.0.0.1≠%,查当前用户用SELECT user, host, plugin FROM mysql.user WHERE user = 'root'; - 执行完必须跟
FLUSH PRIVILEGES;,否则内存权限缓存不更新
哪些 Python 驱动明确支持 caching_sha2_password?别踩版本坑
不是所有新版驱动都开箱即用,有些版本存在 handshake bug 或依赖 OpenSSL 版本:
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
-
mysql-connector-python:必须 ≥ 8.0.11(≤ 8.0.9 不支持;8.0.10 有 TLS 握手缺陷) -
PyMySQL:≥ 1.0.2 安全可用;0.10.x 虽标称支持,但存在 initial handshake 失败问题,跳过不用 -
mysqlclient:≥ 2.0.0 才原生支持;1.4.6 及更早完全不识别该插件 - 连接时若仍报
NotSupportedError: Authentication plugin 'caching_sha2_password' is not supported,先检查pip show mysql-connector-python或对应包版本
Navicat ≤14 连 MySQL 8.0 报错?别折腾驱动替换
Navicat 12/13/14 内嵌的是静态链接的 libmysqlclient,底层调用 OpenSSL 1.0.2,而 caching_sha2_password 要求 OpenSSL 1.1.1+ 的 EVP_PKEY_CTX 接口,dlopen 直接失败,且无 fallback 逻辑。此时升级驱动无效,因为不是 Java 或 Python 层可配置的问题:
- Navicat ≤14.x:唯一可靠解法是服务端降级用户插件(见第一个副标题)
- Navicat ≥15.0.24:原生支持,需确认设置里启用了
SHA256_PASSWORD_AUTHENTICATION=ON - 临时验证是否是 Navicat 问题?用系统自带
mysqlCLI 连一下:mysql -u root -p -h your_host—— 如果 CLI 能连,基本锁定是 Navicat 版本问题
改插件后还要注意什么?安全与场景强相关
mysql_native_password 是 SHA1 哈希 + 明文传输 salt,不走 TLS 就等于裸奔。它只是过渡手段,不是长期方案:
- 内网开发/测试环境:可接受,改完即用
- 生产环境或公网暴露的实例:禁止使用,尤其当未强制
require_secure_transport=ON - 如果必须用
mysql_native_password,至少同步加限制:ALTER USER 'user'@'%' REQUIRE SSL; - 真正可持续的解法永远是升级客户端栈——比如把旧版 Django 的
mysqlclient==1.4.2换成mysqlclient==2.2.4,再配好 TLS 参数
最容易被忽略的一点:MySQL 8.0.4+ 创建的新用户,默认就是 caching_sha2_password,哪怕你没手动指定。所以每次新建账号后,如果要用老工具连,得立刻补一句 ALTER USER ... IDENTIFIED WITH mysql_native_password,不能等出问题了再查。


















