1. 报错现场与问题定位1.1 一个最常见的连接失败场景先复盘一下我实际遇到的场景。那天某个系统上线前要做数据联调,远程连云上 MySQL 8.0 的实例,打开 Navicat,填好公网 IP、端口 3306、用户名和密码,点“测试连接”,几秒之后直接弹出一行红字:2059 - authentication plugin 'caching_sha2_password' cannot be loaded:后面可能还跟着一串关于 plugin 加载失败的提示,具体显示取决于 Navicat 的版本和驱动。如果用的是比较老的版本,甚至只显示2059 - authentication plugin 'caching_sha2_password'就没了下文。第一次遇到这个报错的人很容易懵:账号密码明明是对的,端口也能通,怎么就是连不上?这个问题在 MySQL 8.0 推出之后特别常见,尤其是从 MySQL 5.7 升级过来的环境。你以前的连接方式、驱动、工具配置全都没变,唯独服务端升级到了 8.0 以上,默认认证插件变了,于是旧客户端集体“失联”。先说结论:这是服务端和客户端之间认证插件不兼容导致的,不是网络不通,也不是账号密码错误。解决思路无非两条——要么让账号降低认证方式,要么让客户端升级到支持新认证方式。下面我把原理、实操步骤、常见连带问题都拆开讲。1.2 caching_sha2_password 是从哪里冒出来的MySQL 8.0 发布时,官方把默认认证插件从mysql_native_password换成了caching_sha2_password。这个新插件安全性更高,支持更长的密码杂凑和更安全的传输过程,密码在网络上的传递方式也做了改进。官方期望所有客户端和驱动都跟上新机制。问题就出现在“期望”上。现实里大量工具、SDK 和图形客户端还在用老协议的实现,它们默认只认mysql_native_password。服务端认为默认应该用caching_sha2_password,客户端却只带了自己认知范围内的老插件,两边一握手就对不上,服务端直接拒绝认证,报 2059。理解这个报错的关键点在于:认证插件是在连接初始化阶段就确定的,在密码校验之前就要先协商好“用哪种算法来验证密码”。协商失败后根本走不到密码比对那一步,所以哪怕你的密码是 100% 正确的,一样会报错。1.3 为什么只有部分客户端受影响很多人会问:同一台数据库,别人用命令行能连,我用 Navicat 就不能连,这到底是谁的问题?其实两边都没有“坏”。命令行工具 mysql 自带的客户端通常更新及时,或直接按服务端默认行为工作,所以能适配caching_sha2_password。而 Navicat 这类图形化工具如果版本偏早,内置的数据库驱动没有实现对新认证插件的支持,就只能在握手阶段失败。还有一个常见混淆点:Navicat for MySQL 和 Navicat Premium 不同版本对 MySQL 8 的支持力度不一样。比如某些 10.x 以内的旧版本,连 MySQL 8 时问题比较多;16.0 以上的版本基本已经兼容新认证方式。所以遇到 2059 时先别急着改数据库,看一下自己客户端版本是否太旧,也是排查的重要一环。2. 排查三步走:连接 MySQL 8 之前先确认这三件事2.1 第一步:确认服务端 MySQL 的版本号在动手调整之前,一定要先确认服务端到底是什么版本。如果服务端是 MySQL 5.x,理论上默认认证插件还是mysql_native_password,出现 2059 的概率很低,反而要去查网络、账号授权或 SSL 配置。只有确认是 MySQL 8.0 以及以上版本,认证插件问题才第一个进入怀疑列表。如何确认版本?如果你还能用命令行连接实例,直接执行:SELECT VERSION();或者用:SHOW VARIABLES LIKE 'version_comment';如果命令行也连不进去,可以从云数据库控制台的实例详情页看到版本信息,也能在数据库参数配置里看到default_authentication_plugin的值。千万不要靠猜测来改配置,尤其别直接改了一堆东西最后发现问题根本不在认证插件上。2.2 第二步:确认账号对应的 host 范围很多次排查半天认证插件,最后发现是授权主机范围的问题。MySQL 账号不只是“用户名 + 密码”这么简单,还包含一个host字段,形如'myuser'@'192.168.1.0/255.255.255.0'、'myuser'@'%'之类。你用 Navicat 连接云数据库时,来源 IP 可能是任意公网地址,但如果账号只授权了某个内网网段,哪怕认证插件完全没问题,依然会被拒绝。检查方法:SELECT user, host, plugin FROM mysql.user WHERE user = '你的用户名';这一步可以同时看到两件事——账号授权的主机范围,以及账号当前使用的认证插件。如果host是localhost或某个固定内网 IP,而 Navicat 是从公网连入的,你看到的错误很可能不是 2059,而是Host is not allowed to connect或Access denied。顺手把这一步做掉,能省下后面一大半排查时间。2.3 第三步:确认 Navicat 与驱动对 MySQL 8 的支持情况第三个前置检查是客户端侧。Navicat 官方对 MySQL 8 的支持经历了一个过程,很早期版本确实不能用。我的建议是先去“帮助”菜单里看一下版本号,再对照官方说明确认是否兼容 MySQL 8。如果你用的是较老的 Navicat,有两个选择:升级到新版本,或者按第 3 节的做法把账号认证方式改回mysql_native_password。前者治本,后者治标但见效快。对于生产环境,在不影响业务账号的前提下快速放行是常见做法,但长期维护我还是建议升级客户端。另外要注意:Navicat 只是前端,底层的连接方式也受本机 MySQL 驱动影响。如果系统里装了比较杂的驱动版本,同样会出现类似问题。不过大多数情况直接用 Navicat 自带的驱动就够了,不必自己去折腾。3. 立竿见影的处理:把账号切回 mysql_native_password3.1 先通过命令行进入 MySQL这一步是用最低成本恢复连接。前提是你手头有能用命令行访问 MySQL 的通道,比如云服务器上装了 mysql 客户端,或者能从另一台有权限的内网机器登录。先在服务器或能连通的机器上执行:mysql -u root -p如果 root 账号也进不去,但你有云数据库控制台的管理权限,有的云平台提供了“命令行工具”或“数据管理 DMS”之类的功能,可以借此先把账号调整好。换句话说,无论如何都要先把管理员权限拿回来,否则后面所有 SQL 都没地方执行。3.2 用 ALTER USER 指定认证插件与密码拿到命令行之后,执行下面的语句把当前账号的认证插件改成mysql_native_password,同时重新设置密码:ALTER USER '你的用户名'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';注意这里的'%'要替换成第 2.2 节查到的实际host值。如果账号是'myuser'@'192.168.1.%',那这里的 host 也要写'192.168.1.%',不能想当然地把所有账号都写成%。执行完之后,再执行一次:FLUSH PRIVILEGES;这个操作不是必须的,因为ALTER USER本身会在权限表更新后刷新授权缓存,但加上也不会有问题,尤其你是做迁移或批量调整账号时,习惯性执行一下更稳妥。然后回到 Navicat 重新测试连接。正常情况下,2059 报错会直接消失,连接进入正常的密码校验流程。3.3 后置检查:查看 user 表确认插件已生效为了确认修改真的生效,可以重新查询账号信息:SELECT user, host, plugin FROM mysql.user WHERE user = '你的用户名';执行结果里plugin一列应该已经变为mysql_native_password,而不是之前的caching_sha2_password。这时候 Navicat 再连接,走的就是老协议,自然能过握手阶段。整个过程从执行 SQL 到重新连接,正常情况下一分钟内就能解决,不需要重启 MySQL 服务,也不影响其他账号。3.4 为什么推荐用这种方法而不是全局参数把账号单独改回mysql_native_password,看起来是“倒退回老方案”,但在实际操作里它是损失最小、影响面最可控的方式。理由有三个:第一,它只影响指定的账号和指定的 host 范围,不会改变整个实例对所有新账号的默认认证方式。如果数据库里还有其他业务账号,它们不需要跟着变。第二,它不需要改配置文件,不需要重启 MySQL,也就不会出现重启过程中的短暂不可用。第三,它的执行结果可以在命令行里立即验证,排查起来很直观。我第一次给线上实例处理这个问题时,就没有用全局配置,只改了目标账号,验证连接成功后马上切回正题,后续也没再因为这个账号出现过类似 2059。对于临时应急,“单账号改插件”永远是最稳妥的一步。4. 服务端全局修改:default_authentication_plugin 的上下文与坑4.1 修改 my.cnf 的具体过程如果你管理的是自己搭建的 MySQL,而且希望整个实例对所有新建账号都默认使用mysql_native_password,可以选择修改配置文件。MySQL 8.0 中这个参数对应的系统变量是default_authentication_plugin,但要注意:在 8.0.34 之后的版本中这个变量被弃用,不过仍然能通过配置生效,只是在后续版本里官方更推荐在创建用户时显式指定认证插件。修改方法很简单,找到 MySQL 配置文件my.cnf或my.ini,在[mysqld]段落里加上一行:[mysqld] default_authentication_plugin=mysql_native_password保存后重启 MySQL 服务:systemctl restart mysqld或者用你实际环境里的重启命令。重启之后再新建账号,默认插件就是mysql_native_password。4.2 配置文件重启后验证重启之后,可以通过下面的 SQL 验证全局默认值:SHOW VARIABLES LIKE 'default_authentication_plugin';输出应该是:+-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | mysql_native_password | +-------------------------------+-----------------------+这里我再补充一个实操中容易踩的坑:全局默认值只会影响修改生效之后新建的账号,不会自动帮你转换已经存在的账号。如果你有多个既有账号仍然带着caching_sha2_password,那还需要用第 3.2 节的ALTER USER挨个处理,或者在改配置后重新调整这些老账号。所以我的建议是:在没有特殊合规要求时,不要迷信单靠全局配置就能解决所有账号的兼容问题,它只是给新账号铺了一条老路而已。4.3 这个方案的取舍与适用边界全局修改适合什么场景?比如一批服务器上跑的旧业务系统,好多程序和客户端都只能在老协议下工作,与其每个账号单独调整,不如让新建账号默认就走老协议,减少后续沟通成本。但它也带来了明显的安全性回退,mysql_native_password在身份认证时的密码校验机制相对老,虽然不能说已经彻底不安全,但官方既然在 MySQL 8.0 里把默认换成了caching_sha2_password,就说明新方案在安全设计上有进步。如果数据库实例完全对公网开放,或者你所在团队对账号安全要求比较高,最好还是趁机升级手里的连接工具,而不是让数据库降级去迁就老客户端。另外一个边界是:如果云数据库的管理控制台不允许直接修改某些参数,或者自定义配置文件本来就在受管范围内,你需要先在控制台的参数设置里确认是否可修改。有些云数据库实例的后台参数并不开放,这种情况下直接走账号级ALTER USER是更顺手的路径。5. 云数据库常见问题:端口、安全组、授权与网络策略5.1 安全组与白名单没有放行 MySQL 端口2059 虽然是常用报错,但连接云数据库失败时还有一大批“表亲”问题,它们的现象更像 2059,却根本不是认证插件造成的。最常见的就是安全组或防火墙侧没放行 3306。云数据库通常有两层网络策略:一层是实例所属的安全组,一层是数据库侧的访问白名单。只有两层都允许了你当前的来源 IP,TCP 连接才能建立。如果只是 Navicat 测试连接时报超时,或者错误前缀不是 2059 而是 2003/10060/Can’t connect 之类,基本可以判断是网络层被挡了。不要把 2059 和连接超时混在一起。2059 发生在连接建立之后、认证协商阶段,说明网络已经通了。如果你看到的是连接超时,那要先去查安全组、防火墙、IP 白名单,别在认证插件上浪费时间。5.2 bind-address 和内外网地址不一致自建 MySQL 实例在云服务器上时,还要检查bind-address参数。默认情况下 MySQL 只监听 127.0.0.1,这意味着哪怕你在主机里看着一切正常,本机能连、远程也拿到公网 IP,却依然连不上实例。把bind-address改成0.0.0.0或具体网卡地址后,再重启服务,才能允许外部到达 3306 端口。云数据库托管实例一般不涉及这个问题,因为服务商已经帮你把网络监听和负载做好,直接使用控制台给的连接地址即可。但如果你是在云服务器上自己部署 MySQL,那bind-address就是一个标准的“检查点”:发现报错不是插件问题,先去看它,再去看安全组,顺序上能省不少时间。5.3 授权主机写错导致的 Access denied还有一个高发坑:授权 host 与实际来源 IP 不完全匹配。很多人建账号时图省事写'user'@'localhost',或写了一个固定的内网 IP,结果从 Navicat 的公网出口过来时,MySQL 找不到匹配的账号记录,就会报Access denied for user。这个错误和 2059 不一样,特点是密码明明正确却一直提示 access denied。遇到这种问题,先执行:SELECT user, host FROM mysql.user;然后核对你当前实际的来源 IP 是否落在授权范围内。如果拿不准来源 IP,可以在服务器上看连接日志,或者先在控制台的连接记录里查看最近的失败来源。如果确认host范围写窄了,用下面的语句调整:ALTER USER '你的用户名'@'旧的host' IDENTIFIED WITH mysql_native_password BY '你的密码'; RENAME USER '你的用户名'@'旧的host' TO '你的用户名'@'新的host';或者直接创建一个新的、host 范围正确的账号。这里建议先新建账号再删旧账号,避免中间出现短暂空窗。5.4 SSL 加密连接与首包超时的连带报错云数据库经常会默认要求 SSL 加密连接,或者至少支持但不强制。Navicat 在首次连接时如果服务端要求 SSL,而客户端未能完成加密握手,报错可能会被误认为“认证插件加载失败”。实际上这也是握手阶段的问题,但不是认证算法不匹配,而是加密通道建立失败。排查方法很简单:把 Navicat 连接设置里“使用 SSL”的选项打开,或者根据云数据库提供的 SSL 配置调整。如果是自建 MySQL 没开 SSL,那基本与此无关,还是要回到 2059 的认证插件方案里找答案。还有一种现象是公网链路质量一般时,握手阶段容易超时,现象表现为 Navicat 弹出Lost connection to MySQL server during query或Read timed out。这时候不要和 2059 混在一起,可以尝试调大 Navicat 的高级超时参数,或者检查来源网络是否稳定。6. 实践中的几个细节和一个长久之计6.1 用一条命令为新建账号预置认证方式如果你不想改全局配置,又希望未来新建账号时直接使用mysql_native_password,可以在创建账号的语句里显式指定认证插件:CREATE USER '新用户'@'%' IDENTIFIED WITH mysql_native_password BY '密码';这样创建出来的账号从一开始就是老协议,不需要二次修改。对于业务上确实依赖老客户端的账号,这是一个不用碰全局配置也能保持“默认习惯”的做法。如果之后要切换回来,同样一条ALTER USER改回IDENTIFIED WITH caching_sha2_password BY '密码'即可。切换时不需要额外做什么数据迁移,因为认证插件变化不会影响表结构和已有数据,只会影响后续连接时的身份验证方式。6.2 密码策略与过期时间MySQL 8.0 的密码策略默认可能包含长度、大小写、数字和特殊字符的要求。修改账号认证方式时,如果设置的密码太简单,MySQL 会拒绝执行。比如ALTER USER ... BY '123456'大概率会被ERROR 1819挡住。遇到这类错误,不要以为是自己语法写错,其实只是密码强度不够。另外要留意password_expired字段。如果账号处于密码过期状态,Navicat 连接时也可能出现奇怪的错误提示。可以通过下面的语句把它改为“未过期”:ALTER USER '你的用户名'@'%' IDENTIFIED WITH mysql_native_password BY '新密码';只要这段执行成功,密码自然也就置为未过期状态了。6.3 更好的习惯:及时升级客户端而不是长期兼容老协议最后说一点长远思路。把账号改回mysql_native_password解决眼前问题很快,但如果整个团队有几十个客户端都停留在老版本,长期在数据库侧迁就它们,反而会拖慢未来向更高版本 MySQL 迁移的节奏。我个人实际做过的处理方式是这样:先把现状记录下来,不改任何全局配置;然后统计到底哪些客户端不支持新插件,推动相关人员升级;对于不能立刻升级的临时场景,才用ALTER USER把关键账号切回老协议,并设定一个复查时间点。这样做既保障了业务不中断,又不会让数据库的安全配置一直降级。去年处理某个遗留系统时,三个账号切回老协议先稳住,一周后相关同事更新了工具和驱动,再把账号切回caching_sha2_password,整个过程中没有再做任何全局修改。对比下来,这种“局部临时兼容 + 同步推动升级”的方式,比直接改全局默认配置要干净得多。
1. 报错现场与问题定位1.1 一个最常见的连接失败场景先复盘一下我实际遇到的场景。那天某个系统上线前要做数据联调,远程连云上 MySQL 8.0 的实例,打开 Navicat,填好公网 IP、端口 3306、用户名和密码,点“测试连接”,几秒之后直接弹出一行红字:2059 - authentication plugin 'caching_sha2_password' cannot be loaded:后面可能还跟着一串关于 plugin 加载失败的提示,具体显示取决于 Navicat 的版本和驱动。如果用的是比较老的版本,甚至只显示2059 - authentication plugin 'caching_sha2_password'就没了下文。第一次遇到这个报错的人很容易懵:账号密码明明是对的,端口也能通,怎么就是连不上?这个问题在 MySQL 8.0 推出之后特别常见,尤其是从 MySQL 5.7 升级过来的环境。你以前的连接方式、驱动、工具配置全都没变,唯独服务端升级到了 8.0 以上,默认认证插件变了,于是旧客户端集体“失联”。先说结论:这是服务端和客户端之间认证插件不兼容导致的,不是网络不通,也不是账号密码错误。解决思路无非两条——要么让账号降低认证方式,要么让客户端升级到支持新认证方式。下面我把原理、实操步骤、常见连带问题都拆开讲。1.2 caching_sha2_password 是从哪里冒出来的MySQL 8.0 发布时,官方把默认认证插件从mysql_native_password换成了caching_sha2_password。这个新插件安全性更高,支持更长的密码杂凑和更安全的传输过程,密码在网络上的传递方式也做了改进。官方期望所有客户端和驱动都跟上新机制。问题就出现在“期望”上。现实里大量工具、SDK 和图形客户端还在用老协议的实现,它们默认只认mysql_native_password。服务端认为默认应该用caching_sha2_password,客户端却只带了自己认知范围内的老插件,两边一握手就对不上,服务端直接拒绝认证,报 2059。理解这个报错的关键点在于:认证插件是在连接初始化阶段就确定的,在密码校验之前就要先协商好“用哪种算法来验证密码”。协商失败后根本走不到密码比对那一步,所以哪怕你的密码是 100% 正确的,一样会报错。1.3 为什么只有部分客户端受影响很多人会问:同一台数据库,别人用命令行能连,我用 Navicat 就不能连,这到底是谁的问题?其实两边都没有“坏”。命令行工具 mysql 自带的客户端通常更新及时,或直接按服务端默认行为工作,所以能适配caching_sha2_password。而 Navicat 这类图形化工具如果版本偏早,内置的数据库驱动没有实现对新认证插件的支持,就只能在握手阶段失败。还有一个常见混淆点:Navicat for MySQL 和 Navicat Premium 不同版本对 MySQL 8 的支持力度不一样。比如某些 10.x 以内的旧版本,连 MySQL 8 时问题比较多;16.0 以上的版本基本已经兼容新认证方式。所以遇到 2059 时先别急着改数据库,看一下自己客户端版本是否太旧,也是排查的重要一环。2. 排查三步走:连接 MySQL 8 之前先确认这三件事2.1 第一步:确认服务端 MySQL 的版本号在动手调整之前,一定要先确认服务端到底是什么版本。如果服务端是 MySQL 5.x,理论上默认认证插件还是mysql_native_password,出现 2059 的概率很低,反而要去查网络、账号授权或 SSL 配置。只有确认是 MySQL 8.0 以及以上版本,认证插件问题才第一个进入怀疑列表。如何确认版本?如果你还能用命令行连接实例,直接执行:SELECT VERSION();或者用:SHOW VARIABLES LIKE 'version_comment';如果命令行也连不进去,可以从云数据库控制台的实例详情页看到版本信息,也能在数据库参数配置里看到default_authentication_plugin的值。千万不要靠猜测来改配置,尤其别直接改了一堆东西最后发现问题根本不在认证插件上。2.2 第二步:确认账号对应的 host 范围很多次排查半天认证插件,最后发现是授权主机范围的问题。MySQL 账号不只是“用户名 + 密码”这么简单,还包含一个host字段,形如'myuser'@'192.168.1.0/255.255.255.0'、'myuser'@'%'之类。你用 Navicat 连接云数据库时,来源 IP 可能是任意公网地址,但如果账号只授权了某个内网网段,哪怕认证插件完全没问题,依然会被拒绝。检查方法:SELECT user, host, plugin FROM mysql.user WHERE user = '你的用户名';这一步可以同时看到两件事——账号授权的主机范围,以及账号当前使用的认证插件。如果host是localhost或某个固定内网 IP,而 Navicat 是从公网连入的,你看到的错误很可能不是 2059,而是Host is not allowed to connect或Access denied。顺手把这一步做掉,能省下后面一大半排查时间。2.3 第三步:确认 Navicat 与驱动对 MySQL 8 的支持情况第三个前置检查是客户端侧。Navicat 官方对 MySQL 8 的支持经历了一个过程,很早期版本确实不能用。我的建议是先去“帮助”菜单里看一下版本号,再对照官方说明确认是否兼容 MySQL 8。如果你用的是较老的 Navicat,有两个选择:升级到新版本,或者按第 3 节的做法把账号认证方式改回mysql_native_password。前者治本,后者治标但见效快。对于生产环境,在不影响业务账号的前提下快速放行是常见做法,但长期维护我还是建议升级客户端。另外要注意:Navicat 只是前端,底层的连接方式也受本机 MySQL 驱动影响。如果系统里装了比较杂的驱动版本,同样会出现类似问题。不过大多数情况直接用 Navicat 自带的驱动就够了,不必自己去折腾。3. 立竿见影的处理:把账号切回 mysql_native_password3.1 先通过命令行进入 MySQL这一步是用最低成本恢复连接。前提是你手头有能用命令行访问 MySQL 的通道,比如云服务器上装了 mysql 客户端,或者能从另一台有权限的内网机器登录。先在服务器或能连通的机器上执行:mysql -u root -p如果 root 账号也进不去,但你有云数据库控制台的管理权限,有的云平台提供了“命令行工具”或“数据管理 DMS”之类的功能,可以借此先把账号调整好。换句话说,无论如何都要先把管理员权限拿回来,否则后面所有 SQL 都没地方执行。3.2 用 ALTER USER 指定认证插件与密码拿到命令行之后,执行下面的语句把当前账号的认证插件改成mysql_native_password,同时重新设置密码:ALTER USER '你的用户名'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';注意这里的'%'要替换成第 2.2 节查到的实际host值。如果账号是'myuser'@'192.168.1.%',那这里的 host 也要写'192.168.1.%',不能想当然地把所有账号都写成%。执行完之后,再执行一次:FLUSH PRIVILEGES;这个操作不是必须的,因为ALTER USER本身会在权限表更新后刷新授权缓存,但加上也不会有问题,尤其你是做迁移或批量调整账号时,习惯性执行一下更稳妥。然后回到 Navicat 重新测试连接。正常情况下,2059 报错会直接消失,连接进入正常的密码校验流程。3.3 后置检查:查看 user 表确认插件已生效为了确认修改真的生效,可以重新查询账号信息:SELECT user, host, plugin FROM mysql.user WHERE user = '你的用户名';执行结果里plugin一列应该已经变为mysql_native_password,而不是之前的caching_sha2_password。这时候 Navicat 再连接,走的就是老协议,自然能过握手阶段。整个过程从执行 SQL 到重新连接,正常情况下一分钟内就能解决,不需要重启 MySQL 服务,也不影响其他账号。3.4 为什么推荐用这种方法而不是全局参数把账号单独改回mysql_native_password,看起来是“倒退回老方案”,但在实际操作里它是损失最小、影响面最可控的方式。理由有三个:第一,它只影响指定的账号和指定的 host 范围,不会改变整个实例对所有新账号的默认认证方式。如果数据库里还有其他业务账号,它们不需要跟着变。第二,它不需要改配置文件,不需要重启 MySQL,也就不会出现重启过程中的短暂不可用。第三,它的执行结果可以在命令行里立即验证,排查起来很直观。我第一次给线上实例处理这个问题时,就没有用全局配置,只改了目标账号,验证连接成功后马上切回正题,后续也没再因为这个账号出现过类似 2059。对于临时应急,“单账号改插件”永远是最稳妥的一步。4. 服务端全局修改:default_authentication_plugin 的上下文与坑4.1 修改 my.cnf 的具体过程如果你管理的是自己搭建的 MySQL,而且希望整个实例对所有新建账号都默认使用mysql_native_password,可以选择修改配置文件。MySQL 8.0 中这个参数对应的系统变量是default_authentication_plugin,但要注意:在 8.0.34 之后的版本中这个变量被弃用,不过仍然能通过配置生效,只是在后续版本里官方更推荐在创建用户时显式指定认证插件。修改方法很简单,找到 MySQL 配置文件my.cnf或my.ini,在[mysqld]段落里加上一行:[mysqld] default_authentication_plugin=mysql_native_password保存后重启 MySQL 服务:systemctl restart mysqld或者用你实际环境里的重启命令。重启之后再新建账号,默认插件就是mysql_native_password。4.2 配置文件重启后验证重启之后,可以通过下面的 SQL 验证全局默认值:SHOW VARIABLES LIKE 'default_authentication_plugin';输出应该是:+-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | mysql_native_password | +-------------------------------+-----------------------+这里我再补充一个实操中容易踩的坑:全局默认值只会影响修改生效之后新建的账号,不会自动帮你转换已经存在的账号。如果你有多个既有账号仍然带着caching_sha2_password,那还需要用第 3.2 节的ALTER USER挨个处理,或者在改配置后重新调整这些老账号。所以我的建议是:在没有特殊合规要求时,不要迷信单靠全局配置就能解决所有账号的兼容问题,它只是给新账号铺了一条老路而已。4.3 这个方案的取舍与适用边界全局修改适合什么场景?比如一批服务器上跑的旧业务系统,好多程序和客户端都只能在老协议下工作,与其每个账号单独调整,不如让新建账号默认就走老协议,减少后续沟通成本。但它也带来了明显的安全性回退,mysql_native_password在身份认证时的密码校验机制相对老,虽然不能说已经彻底不安全,但官方既然在 MySQL 8.0 里把默认换成了caching_sha2_password,就说明新方案在安全设计上有进步。如果数据库实例完全对公网开放,或者你所在团队对账号安全要求比较高,最好还是趁机升级手里的连接工具,而不是让数据库降级去迁就老客户端。另外一个边界是:如果云数据库的管理控制台不允许直接修改某些参数,或者自定义配置文件本来就在受管范围内,你需要先在控制台的参数设置里确认是否可修改。有些云数据库实例的后台参数并不开放,这种情况下直接走账号级ALTER USER是更顺手的路径。5. 云数据库常见问题:端口、安全组、授权与网络策略5.1 安全组与白名单没有放行 MySQL 端口2059 虽然是常用报错,但连接云数据库失败时还有一大批“表亲”问题,它们的现象更像 2059,却根本不是认证插件造成的。最常见的就是安全组或防火墙侧没放行 3306。云数据库通常有两层网络策略:一层是实例所属的安全组,一层是数据库侧的访问白名单。只有两层都允许了你当前的来源 IP,TCP 连接才能建立。如果只是 Navicat 测试连接时报超时,或者错误前缀不是 2059 而是 2003/10060/Can’t connect 之类,基本可以判断是网络层被挡了。不要把 2059 和连接超时混在一起。2059 发生在连接建立之后、认证协商阶段,说明网络已经通了。如果你看到的是连接超时,那要先去查安全组、防火墙、IP 白名单,别在认证插件上浪费时间。5.2 bind-address 和内外网地址不一致自建 MySQL 实例在云服务器上时,还要检查bind-address参数。默认情况下 MySQL 只监听 127.0.0.1,这意味着哪怕你在主机里看着一切正常,本机能连、远程也拿到公网 IP,却依然连不上实例。把bind-address改成0.0.0.0或具体网卡地址后,再重启服务,才能允许外部到达 3306 端口。云数据库托管实例一般不涉及这个问题,因为服务商已经帮你把网络监听和负载做好,直接使用控制台给的连接地址即可。但如果你是在云服务器上自己部署 MySQL,那bind-address就是一个标准的“检查点”:发现报错不是插件问题,先去看它,再去看安全组,顺序上能省不少时间。5.3 授权主机写错导致的 Access denied还有一个高发坑:授权 host 与实际来源 IP 不完全匹配。很多人建账号时图省事写'user'@'localhost',或写了一个固定的内网 IP,结果从 Navicat 的公网出口过来时,MySQL 找不到匹配的账号记录,就会报Access denied for user。这个错误和 2059 不一样,特点是密码明明正确却一直提示 access denied。遇到这种问题,先执行:SELECT user, host FROM mysql.user;然后核对你当前实际的来源 IP 是否落在授权范围内。如果拿不准来源 IP,可以在服务器上看连接日志,或者先在控制台的连接记录里查看最近的失败来源。如果确认host范围写窄了,用下面的语句调整:ALTER USER '你的用户名'@'旧的host' IDENTIFIED WITH mysql_native_password BY '你的密码'; RENAME USER '你的用户名'@'旧的host' TO '你的用户名'@'新的host';或者直接创建一个新的、host 范围正确的账号。这里建议先新建账号再删旧账号,避免中间出现短暂空窗。5.4 SSL 加密连接与首包超时的连带报错云数据库经常会默认要求 SSL 加密连接,或者至少支持但不强制。Navicat 在首次连接时如果服务端要求 SSL,而客户端未能完成加密握手,报错可能会被误认为“认证插件加载失败”。实际上这也是握手阶段的问题,但不是认证算法不匹配,而是加密通道建立失败。排查方法很简单:把 Navicat 连接设置里“使用 SSL”的选项打开,或者根据云数据库提供的 SSL 配置调整。如果是自建 MySQL 没开 SSL,那基本与此无关,还是要回到 2059 的认证插件方案里找答案。还有一种现象是公网链路质量一般时,握手阶段容易超时,现象表现为 Navicat 弹出Lost connection to MySQL server during query或Read timed out。这时候不要和 2059 混在一起,可以尝试调大 Navicat 的高级超时参数,或者检查来源网络是否稳定。6. 实践中的几个细节和一个长久之计6.1 用一条命令为新建账号预置认证方式如果你不想改全局配置,又希望未来新建账号时直接使用mysql_native_password,可以在创建账号的语句里显式指定认证插件:CREATE USER '新用户'@'%' IDENTIFIED WITH mysql_native_password BY '密码';这样创建出来的账号从一开始就是老协议,不需要二次修改。对于业务上确实依赖老客户端的账号,这是一个不用碰全局配置也能保持“默认习惯”的做法。如果之后要切换回来,同样一条ALTER USER改回IDENTIFIED WITH caching_sha2_password BY '密码'即可。切换时不需要额外做什么数据迁移,因为认证插件变化不会影响表结构和已有数据,只会影响后续连接时的身份验证方式。6.2 密码策略与过期时间MySQL 8.0 的密码策略默认可能包含长度、大小写、数字和特殊字符的要求。修改账号认证方式时,如果设置的密码太简单,MySQL 会拒绝执行。比如ALTER USER ... BY '123456'大概率会被ERROR 1819挡住。遇到这类错误,不要以为是自己语法写错,其实只是密码强度不够。另外要留意password_expired字段。如果账号处于密码过期状态,Navicat 连接时也可能出现奇怪的错误提示。可以通过下面的语句把它改为“未过期”:ALTER USER '你的用户名'@'%' IDENTIFIED WITH mysql_native_password BY '新密码';只要这段执行成功,密码自然也就置为未过期状态了。6.3 更好的习惯:及时升级客户端而不是长期兼容老协议最后说一点长远思路。把账号改回mysql_native_password解决眼前问题很快,但如果整个团队有几十个客户端都停留在老版本,长期在数据库侧迁就它们,反而会拖慢未来向更高版本 MySQL 迁移的节奏。我个人实际做过的处理方式是这样:先把现状记录下来,不改任何全局配置;然后统计到底哪些客户端不支持新插件,推动相关人员升级;对于不能立刻升级的临时场景,才用ALTER USER把关键账号切回老协议,并设定一个复查时间点。这样做既保障了业务不中断,又不会让数据库的安全配置一直降级。去年处理某个遗留系统时,三个账号切回老协议先稳住,一周后相关同事更新了工具和驱动,再把账号切回caching_sha2_password,整个过程中没有再做任何全局修改。对比下来,这种“局部临时兼容 + 同步推动升级”的方式,比直接改全局默认配置要干净得多。