ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MySQL 8.4升级后ERROR 1524报错:原因与修复方案详解

MySQL 8.4升级后ERROR 1524报错:原因与修复方案详解

刚升级完 MySQL 8.4 的第二天凌晨,值班群就炸了。运维同事把一段报错甩进来:ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded。配上一句"所有用旧密码规则的账号全连不上了,怎么办"。我盯着这行报错看了三秒钟,脑子里立刻浮现出过去一年里在好几个项目里都见过的同款场景——这根本不是一句"重新装一下插件"就能解决的问题,背后是 MySQL 认证插件体系的一次大换血。

这个报错看起来很短,短到很多人会误判它的严重程度。但如果你不清楚 MySQL 8.0 以来认证插件的变化脉络、不知道自己当前版本对旧插件的支持情况,很容易在错误的路线上浪费一两个小时。更麻烦的是,处理不当还会把自己锁在数据库外面。这篇文章我尽量把话说透:这个报错的真正含义、三条可落地的修复路径、以及我在实际运维中踩过的那些细节坑。

1. 认识这条报错:报错信息背后的真实逻辑

1.1 报错发生的三种典型触发场景

先明确一个容易混淆的事实:ERROR 1524不是登录失败时报的错。它在绝大多数情况下,是你主动执行了涉及认证插件的语句时,服务端给出的拒绝响应。最容易触发它的三个场景分别是:

第一,你执行了类似这样的ALTER USER语句,想把某个账号的认证方式改回旧插件:

ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'MyPass_2024';

第二,你在创建新账号时显式指定了旧插件:

CREATE USER 'legacy_app'@'%' IDENTIFIED WITH mysql_native_password BY 'Legacy_123';

第三,你在配置文件中写了default_authentication_plugin=mysql_native_password,然后新创建一个不指定认证插件的用户,服务端按照默认插件去创建账号时同样会抛出这个错误。

注意这三种场景的共性:它们都是"写入"操作,也就是你试图让某个账号使用mysql_native_password这个插件,而服务端告诉你:这个插件没加载,我没法给你安排。

还有一种情况容易被忽略——如果你的历史账号在mysql.user表里的plugin字段本来就写着mysql_native_password,而插件未加载时,这些账号登录会报另外的错误(通常是ERROR 1525 (HY000): Authentication plugin 'mysql_native_password' cannot be loaded)。所以 1524 和 1525 经常成对出现,一个在改账号配置时爆出来,一个在登录时爆出来。后面做诊断时,它们其实指向同一个根源。

1.2 mysql_native_password 的前世今生:为什么好好地说没就没了

要理解这个报错,得先搞清楚mysql_native_password在 MySQL 发展史中的位置。

mysql_native_password是 MySQL 5.x 时代就存在的认证插件,算法基于 SHA1 加一个加盐过程。它在当时是绝对的主流,几乎百分之九十以上的应用连接 MySQL 时都在用它。但是 SHA1 算法这些年已经被认为不够安全,存在已知的理论攻击和实际碰撞风险。所以从 MySQL 8.0 开始,官方把默认认证插件换成了caching_sha2_password,这玩意儿在安全性和性能之间做了更合理的取舍:传输层面支持 RSA 公钥加密或 TLS 保护,同时对高频重复认证做了内存缓存优化,不用每次连接都走完整的加密流程。

关键点来了:MySQL 8.0 刚发布的时候,虽然默认插件换成了新插件,但mysql_native_password仍然是内置的、默认加载的。这就让很多人产生了一种错觉——"这个插件永远都在"。直到 MySQL 8.0.34 开始官方把它标记为废弃,再到 2024 年的 MySQL 8.4 LTS 版本,官方直接把它改成了默认不加载。你需要在启动参数或者配置文件里显式打开,它才存在。到了 MySQL 9.0,这个插件更是被彻底删除,连打开的机会都没有了。

所以当你看到is not loaded这个措辞时,请翻译成更直白的版本:不是"这个插件文件丢了",而是"这个插件在我这个版本里默认不受欢迎了,我故意不加载它"。理解到这一层,后面所有修复思路的出发点就清晰了——要么想办法让它重新加载,要么干脆换个新插件用。

1.3 服务端到底在检查什么

从 MySQL 服务端的源码逻辑来说,当ALTER USER ... IDENTIFIED WITH plugin_name执行时,服务端的账号管理代码会去插件的注册表里查这个插件是否存在。这个注册表就是SHOW PLUGINS命令的输出,如果目标插件不在这张表里,就直接返回ERROR 1524。

这里有一个很多人不理解的细节:MySQL 8.0 里的mysql_native_password是编译进服务端二进制里的,它不像早期版本那样需要通过INSTALL PLUGIN从.so文件里加载。所以你去执行INSTALL PLUGIN mysql_native_password SONAME 'mysql_native_password.so',大概率会得到一个"plugin already loaded"或者找不到对应文件的提示——因为它根本不在插件库里,它是二进制的内置部分。8.4 版本之所以"不加载"这个内置插件,是通过一个开关变量实现的,后面我会详细说。

2. 动手修复前:三个诊断步骤把局面看清楚

接到这个报错,先别急着敲命令。我自己吃过亏:曾经在一台 MySQL 8.0.28 的环境上按 8.4 的修复思路去处理,白白折腾了半天。不同版本、不同插件状态下,正确解法完全不同。

2.1 第一步:确认当前 MySQL 版本

版本决定了你的恢复路线:

版本mysql_native_password 状态是否能启用
MySQL 8.0.0 ~ 8.0.33默认加载可用可直接使用
MySQL 8.0.34 ~ 8.0.x默认加载,但已标记废弃可直接使用
MySQL 8.4 LTS默认不加载可通过配置启用
MySQL 9.0+已从内置中移除无法启用

确认命令很简单,只要你能以任何方式连进去执行:

SELECT VERSION();

如果你已经因为别的原因连不进去了,可以看数据目录下的data目录里有没有版本号文件,或者直接看启动日志。日志里通常在初始化阶段会打一行Version: '8.4.0' socket: ...。

2.2 第二步:确认插件的加载状态

如果还能连进 MySQL,直接执行:

SHOW PLUGINS;

输出里找mysql_native_password这一行,重点看Status字段。如果是ACTIVE,说明插件在,那你面临的可能是别的权限或语法问题;如果这一行根本不存在,说明插件确实没加载。

更精确的查询方式:

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

这个查询的结果更直观:返回空行就是不支持;返回一行且状态是ACTIVE就是可用;如果插件被禁用,这里通常也查不到。

2.3 第三步:摸清受影响的账号范围

无论走哪条修复路线,你都要知道有多少账号依赖旧插件、有多少应用因为它们的认证方式变化会受影响。这一步的执行:

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

把查出来的结果导出一份,后面无论是要批量改密码,还是要跟应用团队对齐客户端兼容性,这份清单都是最基础的依据。

这里我额外提醒一句:在 MySQL 8.0 的mysql.user表里,plugin字段值是NULL的账号表示"使用服务端当前默认认证插件"。这类账号通常不受本次报错影响,修复时不用慌着动它们。真正要处理的就是那些明确写着mysql_native_password的账号。

3. 修复方案一:让旧插件重新上岗

如果你的 MySQL 版本是 8.4 LTS,而业务短期内没法升级客户端驱动(这是最常见的情况,尤其是一些维护多年的老旧 Java/PHP 应用),那最务实的做法就是把mysql_native_password这个内置插件重新启用。这个方案一劳永逸,能让所有历史账号行为完全不变化,但需要重启数据库实例。

3.1 修改配置并重启实例

在my.cnf的[mysqld]段下面增加一行:

[mysqld] mysql_native_password=ON

在 MySQL 8.4 里,mysql_native_password是一个布尔类型的系统变量,默认值是OFF。把它打开之后,服务端在启动阶段就会注册这个内置插件。改完配置,执行一次平滑重启:

mysqladmin -u root -p shutdown # 或者 systemctl restart mysqld

重启完成后,再执行一次SHOW PLUGINS,确认mysql_native_password已经出现并且状态是ACTIVE。到这一步,之前报ERROR 1524的那些ALTER USER、CREATE USER语句就都能正常执行了。

提示:MySQL 8.4 还支持启动时用--mysql-native-password=ON参数临时开启,适合你想临时确认效果、又不想改配置文件的场景。但生产环境建议走配置文件,毕竟你不可能每次重启都手动加参数。

3.2 不想重启?试试在线加载的错误理解

这里必须纠正一个很常见的误区。很多人会想:"这个插件不是内置的吗?那我能不能在运行状态下直接加载它?"

现实是:MySQL 8.4 里mysql_native_password不通过插件库文件加载,所以你在运行状态下执行:

INSTALL PLUGIN mysql_native_password SONAME 'mysql_native_password.so';

你会得到一个"找不到文件"或者类似提示。这个插件没有对应的.so文件,它已经内嵌在二进制里了,启停由mysql_native_password系统变量控制。所以除非你重启,否则没办法在运行中改变它的加载状态。类似的,UNINSTALL PLUGIN也同样不可行。

这就是我开头说"很多人误判"的意思——这个报错不像普通的缺插件问题,它是一个版本策略问题,你的修法必须顺着版本的脾气来。

3.3 启用插件后,如何给受影响账号重置认证方式

插件加载回来后,还得把账号的认证方式拨回正轨。分两种情况:

情况一:你之前执行ALTER USER ... IDENTIFIED WITH mysql_native_password失败了,账号实际还没改成旧插件。这种情况直接重新执行即可:

ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'NewPass_2024';

情况二:你升级后发现已有账号的plugin字段本来就是mysql_native_password,但这些账号登录时无法认证(因为升级后插件还没启用)。这种情况你只需要确认插件状态变为ACTIVE后,这些账号就会自动恢复正常,不需要额外操作。可以随便拿一个账号测一下登录。

补充一个细节:启用插件后,如果你想顺带把服务端的默认认证插件也切回旧插件,可以在[mysqld]段里写:

[mysqld] mysql_native_password=ON default_authentication_plugin=mysql_native_password

但说实话我不建议这么做,除非你的旧客户端实在太多、短期真的切换不完。因为default_authentication_plugin在 MySQL 8.0 中已经废弃,长期来看这个配置早晚要删,越早切换到新插件,你以后越省事。

4. 修复方案二:迁移到新认证插件(推荐路线)

说句心里话,启用旧插件只能算"缓兵之计"。MySQL 官方已经在 9.0 里彻底移除了mysql_native_password,你用 8.4 只是借来的时间,下次再升级还会遇到同样的问题,而且到时候连"启用"这个选项都没有。所以如果你的客户端生态允许,我更推荐直接迁移到caching_sha2_password。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进