☰
MySQL报错Plugin ‘mysql_native_password‘ is not loaded全解析
2026/10/16 7:29:44 网站建设 项目流程

1. 报错的一千种长相与一条固定内核

1.1 你可能遇到的几种报错形态

前两天处理一个数据库连接异常工单,应用侧反馈所有老业务连不上了,报错信息就这么一行:Plugin 'mysql_native_password' is not loaded。一开始以为是数据库宕机,登上去一看实例活着,数据也正常,纯粹是认证插件出了问题。

很多人第一次见到这个错误时,会因为上下文不同而被绕晕。我整理一下最常见的三种形态:

  • 客户端连接时直接抛错:
ERROR 2059 (HY000): Authentication plugin 'mysql_native_password' cannot be loaded
  • 执行CREATE USER或ALTER USER时抛错:
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded
  • 服务器错误日志里出现类似[ERROR] Plugin mysql_native_password could not be loaded的初始化失败信息。

这三种形态背后其实是同一件事:MySQL服务器在处理某个账号的认证请求或账号定义时,发现指定的认证插件在当前实例里根本不可用。

这里面的第一个迷惑点在于,CREATE USER ... IDENTIFIED WITH mysql_native_password BY '...'明明只是写了一条用户定义,为什么非要插件加载?因为MySQL把认证方式也抽象成了插件体系,用户的plugin字段指向一个具体插件。创建或修改账号时,服务器需要先加载该插件,才能正确生成密码哈希、保存认证数据。如果插件不在,就会直接拒绝这条语句。类似地,客户端连接时,服务器读取账号的插件字段,也必须加载插件才能完成挑战-响应流程。

1.2 这行提示在说哪一层的事

我们可以打一个比方:MySQL的认证过程像一个小区门禁,门禁卡上有你的房号信息,而门禁系统需要对应的读卡器驱动才能识别卡片。mysql_native_password就是一套老式门禁卡标准,而MySQL是这个门禁总控。现在总控系统升级到了新门禁协议(caching_sha2_password),但老卡还在用。总控说"老读卡器驱动没装",于是新老卡都进不来——这个报错就是"读卡器驱动未注册"的意思。

把层级拆开看,事情发生在服务器端的认证层,跟客户端关系不大。客户端只负责把密码传给服务器,剩下的校验逻辑全部由服务器端插件完成。所以哪怕你把客户端从老版本换成最新版,只要服务器上插件没加载,问题照样存在。反过来,如果只是某个客户端连不上,其他客户端正常,那通常是客户端不支持新插件,而不是服务器没加载插件。这一层要分清,不然排错方向很容易跑偏。

2. mysql_native_password的前世今生:为什么要为一个旧插件折腾

2.1 它是怎么成为默认认证方式的

mysql_native_password从MySQL 4.1开始出现,一直做到5.7版本都是默认的认证插件。它的核心思路是"挑战-响应":服务器发送一段随机字符串,客户端用密码的SHA1摘要加这段随机字符串做运算,把结果发给服务器,服务器再验算。整个过程密码明文不经过网络,比起更早期的明文传输进步了不少。

它使用的是两次SHA1叠加的哈希策略,具体说是SHA1(SHA1(password))再加一个随机nonce,然后结合一些循环异或操作。这套算法的优点是实现简单、速度快,老客户端、老连接池、各种ORM都把它当默认标准。缺点是抗碰撞能力和安全性已经跟不上时代,尤其是中间人攻击或者服务器端哈希泄露后,破解成本低。所以从8.0开始,MySQL默认认证插件换成了caching_sha2_password,同样有挑战-响应,但用更现代的加密算法,还支持RSA公钥加密传输密码或TLS安全连接。

2.2 在MySQL 8.0里它为什么“退位”了

技术上的问题是旧插件考虑不到的场景越来越多。真正让DBA和运维头大的不是算法本身,而是兼容性。MySQL 8.0升级过程中,很多老业务使用的客户端版本不支持新认证插件,比如某些旧版PHP驱动、旧版JDBC驱动、老的图形客户端工具。它们在不做任何配置的情况下,连新账户时会直接报Authentication plugin 'caching_sha2_password' cannot be loaded。

于是很多人想到的临时办法就是把账号改回mysql_native_password。这时候又撞上本篇标题这个报错:Plugin 'mysql_native_password' is not loaded。为什么会这么巧?因为不少云数据库、容器镜像或定制发行版出于安全考虑,默认禁用了这个旧插件。也就是说,新版MySQL虽然保留了它,但你的部署环境并没有启用它。再加上从8.0.34开始,官方把mysql_native_password标记为废弃,后续版本里再想启用只会越来越麻烦。所以这个"not loaded"背后,既有技术原因,也有环境策略原因。

3. 先确认插件是真的没加载,还是有别的坑

3.1 查看当前插件状态的三板斧

遇到报错先别急着改配置,第一件事是把插件状态看清楚。我在排查时一般按顺序执行下面三步。

第一步,直接看插件列表:

SHOW PLUGINS;

在输出里找到mysql_native_password那一行。如果状态是ACTIVE,说明插件已经加载,报错另有原因;如果是DISABLED,说明插件被禁用;如果完全没这一行,说明插件根本没被加载。

第二步,到系统表里精细化查询:

SELECT PLUGIN_NAME, PLUGIN_STATUS, PLUGIN_TYPE, PLUGIN_LIBRARY FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'mysql_native_password';

PLUGIN_LIBRARY字段能告诉我们插件是不是共享库文件。如果这个字段是NULL,通常表示插件被编译进了mysqld;如果是有值,比如mysql_native_password.so,说明它是从外部动态加载的,文件缺失也会导致加载失败。

第三步,看插件目录和文件是否存在:

SHOW VARIABLES LIKE 'plugin_dir';

执行后拿到目录路径,再到操作系统层面确认插件文件在不在。Linux上一般是lib/plugin/mysql_native_password.so,Windows上是mysql_native_password.dll。如果文件不存在,再怎么INSTALL PLUGIN都是白搭,得先补文件。

3.2 别被“插件未加载”表象骗了

有时候插件其实是加载了的,但账号的plugin字段写错了,或者大小写不一致,也会映射成"is not loaded"。比如某个老库迁移过来时,mysql.user表里的plugin列是空的或乱填的,客户端连接时MySQL会尝试用空插件去认证,自然报错。这种情况要做的是修正用户定义,而不是去动插件。

还有一种情况是服务器启动参数里把插件显式关掉了。MySQL 5.7开始就有mysql_native_password这个系统变量,默认是ON,但某些安全基线或容器编排脚本里会显式加mysql_native_password=OFF。这时候查SHOW PLUGINS会看到DISABLED,处理方式是改配置后重启,或者用SET GLOBAL动态打开。不过要注意,SET GLOBAL mysql_native_password = ON;在很多版本里并不生效,它和普通变量不太一样,最稳妥的办法还是写进配置文件重启。

另外,错误日志里的信息也别忽略。Linux上通常看/var/log/mysql/error.log,里面可能会有类似这样一行:

[ERROR] Failed to load plugin mysql_native_password: plugin disabled or missing runtime

有时候插件是因为依赖的加密库缺失而加载失败,这时候直接启用也没用,得先修复依赖。

4. 让mysql_native_password回到可用的三种路线

4.1 动态安装插件:一条SQL解决当前会话

如果确认插件只是没注册,而插件文件还在,那么最简单的处理是动态安装:

INSTALL PLUGIN mysql_native_password SONAME 'mysql_native_password.so';

在Windows上把mysql_native_password.so换成mysql_native_password.dll即可。执行后立刻生效,不需要重启。这个操作会把插件信息写入mysql.plugin系统表,但注意,这并不代表重启后一定还会加载,因为有些初始化流程会优先读取配置文件里的加载项,而配置文件里可能恰好有禁用的开关。所以动态安装只适合临时救急,不能作为长期方案。

权限上也不要大意,这个语句需要root或者至少拥有INSERT权限于mysql.plugin表。很多业务账号执行时会报权限不足,这就好办了,换DBA账号执行即可。

4.2 写入配置文件:让插件常驻

要让插件在每次启动时都被加载,需要把开关写进my.cnf或my.ini的[mysqld]段。

对于MySQL 8.0以及支持同名系统变量的版本,通常是直接启用开关:

[mysqld] mysql_native_password=ON

如果你的实例里这个变量不存在,或者插件始终没有被内建,那么改用plugin-load-add:

[mysqld] plugin-load-add=mysql_native_password.so

这两种方式不要同时写,避免冲突。写完重启MySQL,然后用第3节的查询命令再次确认状态。我实际遇到过一次,明明配置里写了ON,重启后插件还是DISABLED,后来发现是配置文件名和[mysqld]段写错了位置,前缀被其他段截胡。检查配置时别只看着值,确认生效的是不是这个实例读到的文件。

4.3 针对已有账号的清理和切换

插件加载完成后,接下来处理账号。先看看哪些账号还在用旧插件:

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

如果需要继续使用旧插件,直接重置密码或重新指定认证方式:

ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY '新密码';

如果业务端已经升级,可以顺便把账号切到新插件:

ALTER USER 'app_user'@'%' IDENTIFIED WITH caching_sha2_password BY '新密码';

这里有个实际经验:切换账号前最好先确认这个账号的所有客户端驱动都支持目标插件。最稳妥的办法是先建一个测试账号,用目标插件创建,让应用侧连一把试试,确认没有报错,再批量改老账号。批量改的时候用脚本分批执行,每批之间人工检查一下错误日志,别一把梭。

4.4 从新建数据库的源头避免

如果是新环境,可以在初始化时就规划好,避免上线后被同样的报错堵住。建库时用CREATE USER显式指定插件,例如:

CREATE USER 'new_app'@'%' IDENTIFIED WITH mysql_native_password BY 'abcd1234';

或者反过来,全部默认用新插件,等客户端出问题的时候再个别调整。我更推荐不要修改全局默认认证插件,因为全局改回mysql_native_password会让所有新建账号都依赖这个老认证,等于把临时方案变成了永久债。把选择权留在建号语句里,至少每个账号的用途是清楚的。

5. 复盘一次真实的“升级后全挂”排障过程

5.1 背景:老版本升8.0后旧客户端全部连不上

有次帮一个项目组处理数据库升级,场景很典型:MySQL 5.7原地升到8.0,升级之后所有Java老应用都连不上库,报错是Authentication plugin 'caching_sha2_password' cannot be loaded。项目组的DBA很自然地想把账号改回mysql_native_password,结果执行ALTER USER时弹出了本文标题这行错误:Plugin 'mysql_native_password' is not loaded。

我当时没有直接给方案,而是先拉了一段现场信息。首先在测试连接的命令行里复现报错,确认客户端这边没有问题;接着执行SHOW PLUGINS,发现确实没有mysql_native_password;再检查插件目录,文件还在;最后查配置,发现my.cnf里有一行mysql_native_password=OFF,是部署基线脚本加进去的,目的就是禁用老插件。所以问题的根子不在账号,而在服务器层面的插件开关。

5.2 我们最后的落地方案

清理掉了配置里的OFF,改成ON,重启实例。重启后第一时间用information_schema.PLUGINS确认插件状态恢复为ACTIVE。然后没有急着改所有账号,而是先拿一个低风险账号做测试,改成mysql_native_password,让应用连一把,确认老客户端能通,再写脚本按业务优先级逐批处理。

整个过程中我们留了两个后手:一是把老客户端的升级计划并行推进,承诺过渡期结束后把账号再切回caching_sha2_password;二是排查是否有账号在升级期间被自动迁移到新插件但密码哈希没有正确更新,这类账号即使插件恢复了也可能连不上,需要重新ALTER USER一次。

5.3 这类问题最容易踩的连环坑

我复盘时列了几个常见连环坑,值得提醒:

  • 只动态INSTALL PLUGIN不写配置,重启后被打回原形。
  • 配置文件里用plugin-load-add加载了插件,但没把禁用开关删掉,两行配置互相打架,插件状态依然是DISABLED。
  • 修改了全局插件,但账号仍然指向错误的插件名,比如写了个不存在的插件名,照样报is not loaded。
  • 在从机上执行ALTER USER,因为从机skip-log-bin没开,变更被复制到主库,结果主库又不支持,直接造成主从切换后问题复发。
  • 有些云数据库的控制台会隐藏mysql_native_password相关设置,你在实例参数里看不到,但在连接时又报错。这种时候只能先改账号插件,用新插件连,或者提变更申请开放插件支持。

6. 我在这个错误上沉淀下来的排查习惯

这篇文章是按一个具体报错展开的,其实类似的"插件未加载"排查套路可以复制到其他认证插件上,比如sha256_password、keyring_file等。我现在的习惯是:升级前先导出一份mysql.user全量清单,标记每个账号的插件类型,再确认目标版本对这些插件的支持情况;如果目标版本默认禁用某个插件,就在正式变更前提前把配置文件准备好;变更当天只做开关切换,不做业务账号批量修改,等上线验证通过后再单独安排账号调整。

这个习惯帮我省了很多救火时间。数据库这类问题,大部分都不是真的"坏了",而是插件体系在不同版本之间变了,而部署配置没有跟着变。先把状态查清楚,再决定动哪里,基本上不会跑偏。如果哪天你也在生产环境看到这行报错,别慌,按插件状态、配置项、账号定义三步走,大概率十几分钟就能定位。

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

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

立即咨询