☰
Navicat连接MySQL 8报错2059:caching_sha2_password认证插件详解与三种解决思路
2026/10/21 17:20:27 网站建设 项目流程

1. 报错现场:Navicat 连接 MySQL 8.x 时突然罢工

如果你最近刚装好 MySQL 8.x,或者接手了一个用了新版 MySQL 的项目,打开 Navicat 点连接时大概率会撞上下面这行红字:

2059 - authentication plugin 'caching_sha2_password' cannot be loaded:

翻译成人话就是:MySQL 服务端说“我用的密码认证方式你 Navicat 不支持,咱俩谈不拢”。第一次遇到的朋友很容易懵,明明账号密码没错、端口也通、服务也在跑,为什么就是连不上?

先说结论:这跟账号密码无关,纯粹是 MySQL 8.0 开始把默认的身份认证插件从mysql_native_password换成了caching_sha2_password,而你本地的 Navicat 版本太老,只认旧插件。服务端换了新锁,客户端还在用旧钥匙,自然插不进去。

这个报错我在好几个环境里都真实遇到过——本机连、远程连、Docker 起的 MySQL 都出现过。这篇文章就把三种主流的解决思路完整写一遍,包括底层原理、操作步骤、踩坑点,以及什么情况下选哪种方案最合适。

2. 为什么会有这个错误:认证插件切换的前因后果

2.1 MySQL 8.0 的默认认证机制变化

MySQL 8.0 发布时,官方把默认的身份认证插件从mysql_native_password换成了caching_sha2_password。这俩都是用来验证客户端连接时密码是否正确的东西,但实现方式差异很大。

mysql_native_password是 MySQL 5.x 时代的老方案,基于 SHA1 做密码散列。它的优点是实现简单、兼容性好,几乎所有老客户端都支持;缺点是整个认证过程的安全强度一般,如果连接通道没有加密,密码散列存在被截获后离线爆破的风险。

caching_sha2_password基于 SHA256 密码散列,认证流程更复杂,安全强度更高。它还在服务端加了一层缓存机制,第一次认证成功后,后续短时间内的重复连接可以直接走缓存验证,性能上比逐次全量计算要好。听起来是升级,但代价就是老客户端不认识它。

官方在 MySQL 8.0 里把默认插件改成caching_sha2_password,不是拍脑袋。当时 Oracle 的公告里也说得明白:老的 native password 认证方式已经跟不上安全要求了,新版本必须推动整个生态往强认证迁移。于是,凡是 8.0 之后新建的 MySQL 用户,默认都挂在这个新插件上。

2.2 为什么 Navicat 会翻车

Navicat 其实是支持 MySQL 连接的老牌工具,但它的 Windows 老版本(比如 11.x、12.x 早期版本)内置的 MySQL 客户端库还停留在支持mysql_native_password的阶段。服务端换成了caching_sha2_password,客户端这边没有对应的实现,握手时服务端下发插件名称,客户端尝试加载对应的认证插件,发现没有,于是直接抛出 2059。

这就像两个人在对暗号,服务端说“我用的是新暗号”,客户端翻遍自己口袋,只带了旧暗号,谈判直接破裂。

注意:这个报错不是账号密码输错了,也不是防火墙拦截,更不是 MySQL 服务没启动。你换成老的 MySQL 5.7 连接同样的账密参数,一点毛病没有。

2.3 这个错误的常见出现环境

我统计了一下自己遇到和帮别人排查过的场景,大概是这几类:

出现场景典型原因
本机新装 MySQL 8.x,用 Navicat 连新建用户默认用新插件
从 MySQL 5.7 迁移数据到 8.x,建了新库新用户迁移过程中用户被重建,走了默认插件
Docker 拉取 mysql:8 镜像起服务镜像内默认配置就是新插件
远程服务器 MySQL 8.x,本地 Navicat 连接本地 Navicat 版本过老
使用某些管理面板创建的 MySQL 8 实例面板创建用户时没指定旧插件

清楚了根因,接下来就看怎么选择解决路径。

3. 解决方案一:把用户的认证插件改回 mysql_native_password(最常用)

这个方案的思路很简单:既然服务端换了新锁,客户端又太老开不了,那就把锁换回旧款。对本地开发环境、测试环境来说完全够用,操作最快,且不需要升级客户端。

3.1 具体操作步骤

用命令行连接 MySQL(比如用mysql -u root -p),然后执行:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;

如果 root 用户还涉及远程连接,localhost要改成%或者对应的主机段:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;

如果你想先看看到底哪个用户挂了什么插件,可以查一下:

SELECT user, host, plugin FROM mysql.user;

正常情况下输出里会看到:

+------------------+-----------+-----------------------+ | user | host | plugin | +------------------+-----------+-----------------------+ | root | localhost | caching_sha2_password | | mysql.sys | localhost | caching_sha2_password | +------------------+-----------+-----------------------+

你把 root 行的 plugin 改成mysql_native_password,Navicat 就能恢复正常连接。

3.2 为什么执行完后 Navicat 立刻能连

因为 Navicat 握手时,服务端会告诉它“这个用户用的是mysql_native_password”,客户端发现自己带了这个插件,直接按老流程走密码验证,一次通过。整个过程不需要重启 MySQL,FLUSH PRIVILEGES只是刷新权限表的缓存,让改动立即生效。

3.3 这个方案有什么弊端

先说清楚,改回旧插件本质上是“向下兼容”,安全强度确实不如caching_sha2_password。如果你是公网环境、生产库、或者合规要求比较严的项目,建议优先考虑升级客户端,而不是让服务端降级。

另外注意,如果你后续用 SQL 重置了这个用户的密码,插件不会自动变回去。比如你执行:

ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';

这条语句在 MySQL 8.0 里会按照default_authentication_plugin的配置重新指定插件,如果全局默认还是caching_sha2_password,那你的用户又会被切回新插件。遇到“刚才还好好的,改完密码又 2059 了”的情况,多半就是这原因。所以改密时得显式带插件名:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

3.4 多条命令的完整操作演示

假设你 MySQL 装在本地,root 密码是123456,想彻底解决 Navicat 连接问题,操作是这样的:

mysql -uroot -p # 输入密码登录后,依次执行: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; FLUSH PRIVILEGES; # 验证 SELECT user, host, plugin FROM mysql.user WHERE user = 'root';

输出结果应该变成:

+------+-----------+-----------------------+ | user | host | plugin | +------+-----------+-----------------------+ | root | localhost | mysql_native_password | +------+-----------+-----------------------+

这时候再打开 Navicat,原来的 2059 就不会出现了。这个方法我用的频率最高,因为它只影响目标用户,不会动全局配置,风险可控。

4. 解决方案二:升级 Navicat 到支持新插件的版本(更符合长期利益)

如果你连接的是正式环境、生产数据库,或者你根本不想动服务端任何配置,那么升级客户端才是正确方向。Navicat 在 15.x 之后的版本里已经加入了对caching_sha2_password的支持。

4.1 为什么升级客户端是更优解

MySQL 官方在 8.0 里默认新插件,并承诺后续版本会持续强化这套认证机制。你如果一直用老 Navicat,每连一个新库都要去改服务端用户插件,长期看维护成本很高。而且服务端用户插件改成旧方案后,一些新版 MySQL 的特性(比如更严格的密码校验策略、双密码支持等)在使用时可能受限。

把客户端升级到支持新插件的版本,相当于一步到位,以后建任何新用户都用默认配置,不用再操心兼容性。

4.2 具体怎么确认你的 Navicat 是否支持

打开 Navicat 的“关于”看版本号。如果你当前是 11.x、12.x 或者 13 早期版本,大概率不支持新插件。直接去官网下载最新版本,安装后替换即可。

升级完连接还是失败的话,可以检查一下是不是配置文件残留或者连接串里指定了旧协议。Navicat 的连接设置里,“高级”选项卡如果有“使用旧版加密”之类的选项,取消勾选。

小技巧:升级前先备份一下 Navicat 的连接配置,位置一般在“工具 -> 选项 -> 配置”里可以导出。不然重装后一堆连接信息手动重建,很烦。

4.3 这条路的坑点

升级 Navicat 后连老 MySQL 5.7 实例通常没问题,它向下兼容旧插件。

但如果你的 Navicat 是破解版或者从非官方渠道下载的,升级前记得先导出连接配置,升级完如果授权文件失效,连接配置也会受牵连。

另外,升级不代表服务端原来已经改成旧插件的用户会自动变回新插件,你需要根据自己的需要决定是否再执行一次切换。

5. 解决方案三:直接改 MySQL 全局默认认证插件(一劳永逸)

前面两个方案是针对单用户的,如果想让这台 MySQL 之后新建的所有用户默认都用mysql_native_password,可以修改服务端配置。

5.1 修改 my.cnf / my.ini

在 MySQL 配置文件里的[mysqld]段落下加一行:

default_authentication_plugin=mysql_native_password

Linux 下配置文件一般在/etc/mysql/mysql.conf.d/mysqld.cnf或者/etc/my.cnf,Windows 下在 MySQL 的安装目录里找my.ini。改完重启 MySQL:

systemctl restart mysql

或者 Windows 服务里重启 MySQL 服务。

重启后,新建用户默认就会用旧插件:

CREATE USER 'test_user'@'localhost' IDENTIFIED BY '123456'; SELECT user, host, plugin FROM mysql.user WHERE user = 'test_user';

你会看到新用户已经挂上了mysql_native_password。

5.2 这个方案适合什么场景

只推荐在本地开发环境、内网测试环境使用。生产环境不要说改全局默认,连单用户降级插件都要走审批,最好还是保持默认新插件 + 升级客户端。

另外一个很常见的变体:你用的是云数据库 RDS,控制台登录时没有权限改配置文件,这种情况就别想着改全局了,老老实实按方案一走单用户修改,或者升级客户端。

5.3 一个容易被人忽略的细节

MySQL 8.0.34 之后,官方其实已经将mysql_native_password标记为废弃(deprecated),并且从 8.4 版本开始默认禁用这个插件。如果你用的是非常新的 MySQL 版本,执行ALTER USER ... IDENTIFIED WITH mysql_native_password可能会直接报错提示插件不可用。

这种情况下,你就需要显式启用旧插件,在配置文件里加:

[mysqld] mysql_native_password=ON

然后再执行 ALTER USER 语句。说实话,这条路已经是逆着官方方向走了,能用但不够优雅。我的建议是尽量走升级 Navicat 的路子,省心。

6. 权限表视角:root 之外的其他用户遇到 2059 怎么处理

日常开发中,很多项目不会用 root 连接数据库,而是由 DBA 创建专用账号。这些专用账号如果也遇到 2059,处理思路一样,但需要额外注意权限范围。

6.1 只改应用账号,不动 root

应用账号一般长这样:

CREATE USER 'app_user'@'%' IDENTIFIED BY 'AppPassword123'; GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'%';

如果这个账号连不上,执行:

ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'AppPassword123'; FLUSH PRIVILEGES;

只改这个账号,不影响 root 和其他用户。

6.2 区分 localhost / % / 具体 IP

MySQL 的用户是“用户名 + 主机”二元组,'app_user'@'localhost'和'app_user'@'%'是两个完全独立的账号。改错主机段,连接还是报错。

排查的时候先执行:

SELECT user, host, plugin FROM mysql.user WHERE user = 'app_user';

看清楚连接来源对应的 host 是哪个,再执行对应的 ALTER。比如你在公司内网用 192.168.1.50 连接,但账号只建了'app_user'@'%',那就要改%那条。

6.3 密码策略可能成为隐形门槛

MySQL 8.0 默认启用了密码校验组件,太简单的密码(比如123456)在建用户时直接会被拒掉。但你要是用IDENTIFIED WITH mysql_native_password BY '123456'这种写法,部分版本也会触发密码强度校验失败。

遇到ERROR 1819 (HY000): Your password does not satisfy the current policy requirements时,要么把密码改复杂,要么临时调低校验等级:

SET GLOBAL validate_password.policy = LOW; SET GLOBAL validate_password.length = 6;

需要说明的是,这是全局设置,测试环境可以用,生产环境不建议动。

7. 生产环境迁移的注意点:从 5.7 升到 8.x 时的 2059

MySQL 5.7 迁到 8.x 是很多团队都会经历的。数据迁移本身有官方工具可以操作,但这中间最容易忽略的就是认证插件差异,尤其在代码里、配置里、快捷连接工具里全部都要跟着适配。

7.1 迁移后 2059 为什么出现的概率极高

原因很简单,老库里的所有账号都是mysql_native_password,迁移到新库后,如果通过工具重建账号、导入用户表,新的 MySQL 8.x 默认插件会把新建的用户设置成caching_sha2_password。如果你的中间件、定时任务、BI 工具用的驱动还是老版本,连上就报 2059。

更麻烦的是,有些迁移工具只迁移数据不迁移用户,迁移完你需要手动重建所有业务账号,重建时没显式指定插件,默认就走新插件。

7.2 迁移时一次性把所有账号改成旧插件

你可以用 SQL 动态生成 ALTER 语句,一条条执行。比如在旧库导出用户清单,然后拼接语句:

SELECT CONCAT('ALTER USER ''', user, '''@''', host, ''' IDENTIFIED WITH mysql_native_password BY ''密码'';') FROM mysql.user WHERE plugin = 'caching_sha2_password' AND user NOT IN ('mysql.sys', 'mysql.session', 'mysql.infoschema');

把输出结果复制到新库执行。注意密码部分需要手动补全,这个 SQL 只是方便你快速生成语句。改完后不需要重启 MySQL。

7.3 应用连接串里的参数适配

如果你的应用代码用 JDBC 连接 MySQL 8.x,且服务端用户还是新插件,那么驱动版本也很关键。使用老版本驱动(比如 mysql-connector-java 5.1.x)连接时,即使服务端没有强制要求新插件,也可能出现类似报错。升级驱动到 8.0.x 之后,连接串可以加上:

jdbc:mysql://localhost:3306/db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

allowPublicKeyRetrieval=true这个参数只有在连接方式不支持 SSL 时才需要。如果你的服务器开启了 SSL,那么这一行不写也没问题。

7.4 迁移后验证清单

迁移完别急着收工,我习惯按这个清单过一遍:

  1. 用命令行本地登录,确认账号密码可用;
  2. 用 Navicat 分别连接 localhost 和远程地址;
  3. 用应用代码跑一遍核心接口;
  4. 检查慢查询日志里有没有认证失败的记录。

8. Docker 部署 MySQL 8.x 时 2059 的处理细节

Docker 跑 MySQL 是另一类高频场景,处理思路略有不同,因为容器环境里改配置、改用户的路子都受镜像机制影响。

8.1 容器内的快速解决方式

先用 docker exec 进入容器:

docker exec -it mysql8 mysql -uroot -p

然后执行:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;

这个方案和前面方案一相同,但注意容器重启后 MySQL 服务会重新启动,用户表是持久化在数据卷里的,所以改一次就长期有效,不需要每次都改。

8.2 通过环境变量直接创建旧插件用户(最省事)

如果你还没创建容器,可以在docker run时挂一个初始化脚本:

docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD=rootpass \ -v /opt/mysql-init:/docker-entrypoint-initdb.d \ -p 3306:3306 \ mysql:8

在/opt/mysql-init/init.sql里写入:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'rootpass'; FLUSH PRIVILEGES;

容器首次初始化的时候会自动执行这个脚本,之后启动就默认带旧插件。

8.3 容器场景下升级客户端反而是更干净的路

有的人图省事,直接改容器内 MySQL 配置,挂载自定义 my.cnf 把默认插件设为旧插件,这确实能解决,但容器重建时你很容易忘了这回事,而且这个配置本身就是逆着官方默认方向走的。毕竟是本地开发环境,怎么方便怎么来,但如果你这个容器是为了模拟生产环境,那我不建议你改配置,保持默认新插件,然后用新版 Navicat 连接,才是最贴合真实线上环境的做法。

9. 我的选择建议与踩坑总结

9.1 三种方案怎么选

场景推荐方案原因
本地开发、随便连连方案一:改用户插件最快,影响面最小
正式环境、长期使用方案二:升级 Navicat服务端保持强认证,客户端适配新标准
测试环境新建用户量大方案三:改全局默认插件省得每个用户单独改
Docker 一次性起服务方案一或初始化脚本起完就能连,脚本可复用
生产迁移 5.7 -> 8.x方案二 + 升级驱动保证线上安全等级不下滑

9.2 我踩过的三个真实坑,写出来给大家避开

第一个坑:只改了 localhost 的 root,忘了 Navicat 用的是远程地址连接。Navicat 连接配置里如果主机填的是127.0.0.1或局域网 IP,MySQL 匹配的是'root'@'%'或'root'@'127.0.0.1'而不是'root'@'localhost'。结果就是明明执行了 ALTER,Navicat 还是报 2059,瞎折腾半小时。

第二个坑:密码改完后插件又变回去了。我之前给测试环境改过 root 用户插件,后来同事重置了一次密码,用的语句没带插件名,结果 MySQL 8.0 默认又把插件切回caching_sha2_password,Navicat 再次报 2059。所以团队里如果有人会操作数据库,最好在文档里注明“改密必须带 WITH mysql_native_password”。

第三个坑:升级 Navicat 后连接串里的端口问题。有次升级完,旧版本里保存的连接默认走 3306 没问题,但新版本里如果之前选过 SSH 隧道,升级后部分配置会重置。连接超时的时候别急着怀疑服务端,重新检查一下连接配置的端口和 SSH 开关。

9.3 日常连接 MySQL 8.x 的预防思路

与其每次被 2059 搞一次,不如提前做点预防工作:

  1. 统一客户端版本:团队内部约定 Navicat 最低版本,避免每个人报错原因各不相同。
  2. 建用户时就确定插件:创建账号时顺手把WITH mysql_native_password写进去,后续省事。
  3. 配置管理文档化:任何 ALTER USER、CREATE USER 操作都留痕,尤其是插件相关的变更。
  4. 定期检查用户插件矩阵:每月执行一次上面提到的SELECT user, host, plugin FROM mysql.user,发现意外的旧插件用户及时评估切换。

我个人的体会是:这个错误本身不复杂,但因为它牵涉到客户端、服务端、账号权限、配置持久化几个层面,排查链路长,最容易在细节上翻车。只要把插件原理和修改路径搞清楚,它也就是顺手一条 SQL 的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询