
这个报错我前前后后帮同事处理了不下十次每次都是新装好的 MySQL 8.x 用旧工具一连接就蹦出来。第一次遇到的时候我也懵了一下后来把原理摸透了才知道这根本不是啥玄学问题纯粹是 MySQL 8 改了默认的认证插件把老客户端的路子堵死了。先把这个报错翻译成人话1251 - Client does not support authentication protocol requested by server意思是客户端不认服务器要求的认证协议。注意这话说的不是密码错误也不是用户名不存在就是双方在“握手”阶段对不上暗号。1. 错误原因剖析从 MySQL 8.0 的默认认证插件说起1.1 新版 MySQL 换掉了沿用二十年的老规矩MySQL 5.7 及更早版本默认的认证插件叫mysql_native_password本质是 SHA1 密码散列校验流程简单粗暴客户端把密码做一次 SHA1服务器拿存储的散列值比对。这个方案从 MySQL 4.1 用到现在兼容性极好几乎所有语言驱动、GUI 工具都支持。MySQL 8.0 开始官方把默认认证插件换成了caching_sha2_password。这个新插件性能更好、安全性更高核心变化在于密码校验加入了随机挑战机制和服务端公钥交换整个验证流程和老的mysql_native_password完全不同。问题就出在这里——你用老版本的客户端比如古老的 Navicat 11、PHP 5.x 的 mysql 扩展、某些旧版 Java 驱动、甚至系统自带的 mysql 5.7 命令行工具去连新版 MySQL 8 服务器客户端根本不认识caching_sha2_password这个新协议自然直接甩你一脸 1251。注意连接报 1251和密码对不对没关系。哪怕你密码输对了客户端不认识新认证协议照样报这个错。1.2 具体是哪类客户端容易踩坑结合我实际处理过的案例大概分这几类老版本 GUI 工具Navicat 15 之前的版本、SQLyog、Workbench 老版本这些都是重灾区。老版本语言驱动PHP 7.2 之前的mysql扩展、Python 的mysql-pythonMySQLdb、Java 的mysql-connector-java5.1.x 及更早。系统自带的命令行工具比如你 CentOS 7 上通过 yum 装的 mysql 5.7 客户端去连远程的 8.0 服务器。这里有一点值得说清楚同一个报错 1251触发机制在不同工具里可能略有差异但根子都在认证插件不兼容。有些新版工具报错文案是Authentication plugin caching_sha2_password cannot be loaded那是另一个层面的问题客户端没加载插件但解决思路是完全一致的。2. 解决前的准备工作先摸清你的环境和版本2.1 三步确认法先诊断再动手别上来就改配置先花两分钟确认现状避免方向性错误。第一步确认服务器端 MySQL 版本和当前默认认证插件-- 登录 MySQL 后执行 SELECT VERSION(); SHOW VARIABLES LIKE default_authentication_plugin;如果default_authentication_plugin的值是caching_sha2_password那 1251 的根源基本就坐实了。第二步确认目标用户的当前认证插件SELECT user, host, plugin FROM mysql.user WHERE user 你的用户名;第三步确认你本地客户端版本# 命令行客户端 mysql --version # 如果是 Navicat查看 帮助 - 关于如果是代码连接看驱动包版本把这三步的信息凑齐问题定位就非常清晰了服务器是 8.0默认插件是 caching_sha2_password用户也是 caching_sha2_password而你的客户端太老只认 mysql_native_password。2.2 两个方向怎么选弄明白原因之后解决方向其实就两条方向 A改服务器端配置和用户认证插件——让服务器“向下兼容”老客户端。方向 B升级你的客户端/驱动——让客户端跟上新协议。方向 B 当然最彻底符合长期安全趋势。但现实中很多场景没法立刻升级生产环境老代码不能动、客户指定的老工具不能换、临时要连一下别人的库你手上只有旧工具——这时候方向 A 就是最快的救命稻草。我个人建议能升级客户端就升级不能升级再改服务器。这篇博文重点讲方向 A 的具体操作因为它通用性最强而且就算你以后升级了客户端这些命令也能帮你把特定用户切回老插件。3. 核心解决方案三种改法按场景对号入座3.1 方案一只改特定用户的认证插件最常用最安全这个方案只影响你指定的用户不动全局配置风险最小。以 root 用户为例登录 MySQL 命令行后执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;如果 root 的 host 不是 localhost比如你从远程 IP 连接host 是%或者具体 IP那要按实际的 host 来比如ALTER USER root% IDENTIFIED WITH mysql_native_password BY 你的密码;执行完再用老客户端试一下连接。我处理过的案例里这条命令 90% 的情况都能当场解决问题。要注意的是这里我把密码也一起重置了。如果你不想改密码但又必须指定认证插件MySQL 8 的语法要求认证插件和密码必须绑定在一起。在实际操作中很多人图省事就直接把密码重设成原来的反正效果一样。注意host 写错会导致报Unknown user之类的错误。一定要先查mysql.user表里这个用户实际有哪些 host。另一种常见写法是直接改表但我不推荐——ALTER USER 是官方正道改表容易引发权限刷新不及时的问题。3.2 方案二修改 MySQL 全局配置让新用户默认走老插件如果你不想每次建用户都手动指定插件可以直接改配置文件把全局默认认证插件改回mysql_native_password。Linux 下编辑/etc/my.cnf或/etc/mysql/my.cnf具体路径看你安装方式Windows 下编辑my.ini在[mysqld]段下加一行[mysqld] default_authentication_pluginmysql_native_password然后重启 MySQL 服务# systemd 系统 systemctl restart mysqld # 或 systemctl restart mysql # Windows 服务 net stop mysql net start mysql改完之后新建的用户默认就是mysql_native_password插件。注意这个配置只影响新建用户之前已经存在的用户比如 root插件不会自动变需要手动执行 ALTER USER 切换。所以改完配置后老用户还得再用一遍方案一的命令。3.3 方案三新建一个专门用于旧客户端连接的用户如果你的服务器上有多个应用共存不想动 root 的认证方式也不想改全局配置那就新建一个独立用户CREATE USER legacy_app% IDENTIFIED WITH mysql_native_password BY StrongPss123; GRANT ALL PRIVILEGES ON 你的数据库.* TO legacy_app%; FLUSH PRIVILEGES;这个方案的好处是隔离性好老客户端用legacy_app这个用户连接新应用继续用caching_sha2_password认证的其他用户互不干扰。权限也可以按需给最小化授权更安全。不过生产环境给新用户授权时建议按实际需求精确授权不要一上来就ALL PRIVILEGES。给个 SELECT、INSERT、UPDATE、DELETE 就差不多了避免过度授权留下安全隐患。3.4 三种方案的横向对比方案操作复杂度影响范围适合场景只改特定用户低单用户个人开发机、临时连接改全局配置中所有新用户老项目整体迁移到 8.0客户端短期内不升级新建用户低新用户多应用共存需要隔离权限说实话方案一是我最常用的。它最精准一行命令解决不碰全局配置出问题也容易回滚再 ALTER 回去就行。4. 实操过程记录从报错到解决的全流程4.1 一个真实案例Windows 上装的 MySQL 8.0Navicat 死活连不上有一次帮一个同事处理问题他的环境是 Windows 10装的 MySQL 8.0.30用 Navicat 15 连接时弹出 1251 报错。我先在命令行登录 MySQLmysql -uroot -p然后确认版本和插件SELECT VERSION(); SHOW VARIABLES LIKE default_authentication_plugin;结果值分别是8.0.30和caching_sha2_passwordroot 用户的 plugin 也是caching_sha2_password。他本地的 Navicat 15 是老协议客户端情况完全吻合。接下来我直接执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 他原来的密码; FLUSH PRIVILEGES;执行完让他重新点连接一次成功。全程不到两分钟。4.2 Docker 容器里的 MySQL 同样适用很多人用 Docker 跑 MySQL容器里的处理方式和本机一样只是要先进容器。我用的是这样的流程docker exec -it mysql8 bash mysql -uroot -p进去之后执行同样的 ALTER USER 命令。如果你是用docker-compose部署的注意 MySQL 容器重启后数据不会丢数据卷挂载在宿主机所以 ALTER USER 的结果也一直在。这里插一句如果你是通过 Docker 环境变量初始化的 root 用户默认 host 是%所以 ALTER USER 时要写成ALTER USER root% IDENTIFIED WITH mysql_native_password BY 你的密码;4.3 群晖、绿联 NAS 上安装 MySQL 的场景看到热搜里有“绿联nas 安装mysql”这类 NAS 自带的 MySQL 或者通过 Docker 安装的 MySQL很多也是 8.x。后续用电脑上的客户端去连一样会遇到 1251。处理方法同 4.2先进 NAS 的 Docker 容器再执行 ALTER USER 命令。我帮群晖用户处理过一次流程完全一样没有任何特殊之处。5. 常见问题与排查技巧实录5.1 明明改了认证插件还是报 1251这类情况多半是改错用户了。比如你一直用rootlocalhost连接但实际连接时是通过127.0.0.1走的 TCP/IPMySQL 匹配用户时可能用的是rootlocalhost要看 skip_name_resolve 配置也可能匹配到root127.0.0.1或root%。这里有个很容易踩的坑MySQL 的客户端身份认证是根据“用户名 来源 IP”双重匹配的。如果表里有多个同名的 root但 host 不同你改的 host 和实际连接的 host 不一致改了等于白改。建议操作把三个常见组合都查一遍全部改成一致的SELECT user, host, plugin FROM mysql.user WHERE user root;如果有多个 host就把你用到的那个改掉或者干脆都改。5.2 MySQL 8.4/9.x 还能用这套方案吗这就是一个值得展开讲的风险提示。在 MySQL 8.0.x 系列里mysql_native_password插件还可以用只是默认不启用。但从 MySQL 8.4LTS 版本开始官方已经默认禁用mysql_native_password插件了配置文件里写default_authentication_pluginmysql_native_password可能会直接导致 MySQL 启动失败或者提示 unknown variable。所以如果你用的是 8.4 或更新的版本遇到老的客户端连不上不要想着去改服务器端了老老实实升级客户端/驱动才是正路。热搜词里有mysql 8.4.11 lts数据库服务器的下载、解压及配置说明确实有人在新版本上折腾我的建议很直接新版本 老客户端这条路走不通官方在设计上就是要淘汰老协议。5.3 执行 ALTER USER 后提示密码格式问题MySQL 8 对新密码有自己的安全策略默认validate_password插件会检查强度。如果你设置太简单的密码会报ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。办法是先临时的强密码改过去登录后再用ALTER USER调整策略或者干脆就设一个满足要求的强密码大小写数字特殊字符8位以上省得折腾。5.4 能不能用图形化工具直接改Workbench 倒是可以在左侧面板选中用户右键编辑在“Authentication Type”里选回mysql_native_password。不过说实话命令行两行就能解决的问题没必要开图形化工具绕一圈还容易漏掉刷新权限那一步。5.5 1251 和 1250 的区分有人在网上搜的时候会遇到 1250 错误那个是客户端版本过老、SQL 语法不兼容的问题和认证插件无关。1251 专指认证协议不一致。区分方法很简单1250 一般是执行 SQL 时报错1251 是在建立连接阶段就报错。两个问题处理方法完全不同。6. 实操心得与避坑建议6.1 我的日常处理优先级处理了这么多轮 1251我自己总结了一套稳妥的决策顺序第一步确认 MySQL 版本。如果是 8.0.x走第二步如果是 8.4直接劝你去升级客户端别折腾服务器端省时间又安全。第二步确认当前用户插件。如果确认是caching_sha2_password执行 ALTER USER 切到老插件。第三步连接测试。如果还报错查用户 host 匹配如果变成密码相关错误再查密码策略。这个顺序能覆盖九成以上的场景剩下的都是一些极端环境逐项排查就行。6.2 一个值得养成的好习惯改完任何认证相关的配置记得执行FLUSH PRIVILEGES;。虽然很多场景下 ALTER USER 会自动生效但加上这一句能让权限缓存立即刷新避免各种诡异的小问题。这个习惯成本极低但能省掉不少排查时间。6.3 长期安全角度的建议我必须坦白说把用户切回mysql_native_password是暂时的兼容手段。你自己玩、开发环境用没问题生产环境长期这样做我是不推荐的。caching_sha2_password在安全性和性能上都有优势长期方案还是尽快升级客户端/驱动。把当前方案理解为过渡期策略而不是永久配置心态会正很多。6.4 最后再分享一个命令行诊断小技巧如果公司网络里有多个 MySQL 实例你又经常要排这种连接问题建议在自己电脑上装一个 mysql 8.0 的客户端连接测试时开通用 verbose 看协议细节mysql -h你的主机 -P端口 -u用户 -p --protocolTCP --verbose --verbose输出里会显示认证插件的协商过程看到caching_sha2_password但客户端不支持问题就实锤了。配合SHOW VARIABLES LIKE default_authentication_plugin的输出整个诊断链路基本能在一分钟内走完。回头再看 1251 这个报错本质就一句话版本的洪流把老客户端甩在了岸上。解法也一句话要么让服务器说老客户端听得懂的话要么让客户端学会新话术。希望这篇分享能帮你少走几个来回至少下次再见到 1251你不会再对着密码发呆半天——先查认证插件问题就解决一半了。