MySQL 9.7 升级前先清账号:native_password 在 9.0 就没了,原地回滚也不行
参考链接:
- MySQL 9.7 Release Notes:
- 9.7 降级章节:
- Clone 插件限制:
- 8.4 手册 native pluggable authentication:
- 9.0.0 release notes(移除说明):
- Oracle 博客「MySQL 9.0 – it's time to abandon the weak authentication method」:
- 9.7 手册 8.4.1.2 SHA-256 Pluggable Authentication:
- Percona Server 9.7 降级文档:
一个具体的失败场景
8.4 的库计划升到 9.7 LTS。测试环境能起来,应用连不上,日志里是 Plugin 'mysql_native_password' is not loaded 或认证被拒;复制也断,报没有权限认证。
这不是配置漏了,是 9.0 起服务端的 native 认证插件已经被删掉了。
时间线要记清
- MySQL 8.0.34:
mysql_native_password标记弃用。 - MySQL 8.4:服务端插件默认不加载(要
--mysql-native-password=ON才启用)。 - MySQL 9.0.0:服务端插件移除。同时移除
--mysql-native-password、--mysql-native-password-proxy-users两个选项,以及default_authentication_plugin系统变量。客户端侧的插件保留,但改成动态加载插件。 - MySQL 9.7.0(2026-04-21 GA,LTS):
caching_sha2_password是默认认证插件,mysql_native_password不再可用。9.7 同时支持caching_sha2_password的 PBKDF2 存储格式(PBKDF2 with SHA512),官方说法是客户端不需要改,管理员可以指定偏好的存储格式(具体变量名以 9.7 文档为准,未实测)。sha256_password已弃用,后续版本会移除。 - 9.7.3(2026-08-18):只是针对 MySQL Server docker 镜像的 Critical Security Patch Update,不是常规维护版本。
升级前先跑三条查询
-- 1. 还有多少账号不是 caching_sha2_password
SELECT plugin, COUNT(*) FROM mysql.user GROUP BY plugin;
-- 2. 谁是 native,尤其是复制账号和应用账号
SELECT user, host, plugin FROM mysql.user
WHERE plugin <> 'caching_sha2_password';
-- 3. 复制通道用哪个账号认证
SELECT channel_name, user_name, host FROM performance_schema.replication_applier_status_by_worker LIMIT 5;
再看配置文件里有没有 default_authentication_plugin、mysql_native_password=ON 这类 9.x 已删除的项。留着不会「无效但可忽略」:9.x 启动时会按未知变量处理(具体表现随启动方式不同,需在测试机验证)。
迁移账号:hash 不能换算,只能重设密码
native 的 hash 是 SHA-1 无盐单轮,caching_sha2_password 是加盐多轮,两者不能互相转换。也就是说 ALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...' 必须带一个明文新密码,原来那条 hash 用不上。
这是升级最容易被低估的成本:不是改一行配置,而是要走一遍改密流程。
ALTER USER 'app'@'10.%' IDENTIFIED WITH caching_sha2_password BY '新密码';
FLUSH PRIVILEGES;
几个具体约束:
- 复制账号要在源库上重建为
caching_sha2_password,否则升级后 inbound channel 认证不过;升级后对 native 账号做任何改密操作也会打断复制。 - 老 connector 直接出局。PHP 7.2 时代的 mysqlnd 这类不支持
caching_sha2_password的客户端,连 9.x 会认证失败,唯一办法是升 connector / 升语言运行时。这也是「只升数据库不升应用镜像」最常见的一次翻车。 - 非 TLS 连接要注意公钥交换。
caching_sha2_password首次认证在明文连接上走 RSA 公钥,JDBC 会报Public Key Retrieval is not allowed,需要显式allowPublicKeyRetrieval=true(生产更该直接上 TLS)。Go 的 go-sql-driver 同理,建议配tls=或提供 server public key,别指望默认值。
回滚这件事:9.7 降回 8.4 没有原地方案
官方降级表写得很明确:
- LTS 系列内部(9.7.y → 9.7.x):可以原地降级、逻辑导出导入、Clone、或复制。
- 跨 LTS 系列(9.7.x → 8.4.y):只支持逻辑导出导入或基于复制,而且仅用于回滚场景,前提是数据里没有用到 9.7 独有的特性。
Clone 插件的限制更硬:不能跨 series 克隆(8.4 与 9.7 之间不行),9.7 只能往更高且相邻的系列克隆,明确写了 9.7 到 8.4 不可克隆。降级到 8.0 或更早不支持。
推论是三条工程约束:
- 升级前必须有可验证的逻辑备份(
mysqldump/ MySQL Shell dump),或者留一台 8.4 的旧实例做复制回切,别指望「换回二进制重启」。 - 升级后一旦用了 9.7 独有特性(例如 9.7 的 masking policy、JSON Duality View 的 DML),跨系列回滚就不成立了,只能从升级前备份恢复。
- 应用侧要能回到 8.4 的认证方式,也就是说改密过程中要保留可回退的账号方案(例如并行建一个
caching_sha2_password账号,验证通过后再切,而不是直接ALTER掉唯一的账号)。
周边组件的坑
- ProxySQL 在 9.7 环境里 binlog reader 可能初始化失败,原因是它还在用
SHOW MASTER STATUS这类旧命令。Percona 文档给的办法是打开terminology_use_previous,但明确说了只解决术语兼容,不保证修掉全部失败。计划里要留出代理层升级 / 替换的时间。 - MySQL Connectors、Shell、Router、Operator 是单一版本号、兼容多个 Server 版本(例如 Connector/Python 9.7.0 兼容 8.0、8.4、9.x)。Server 升级不等于客户端库自动跟着对,要单独确认应用镜像里的 connector 版本。
- 版本号本身也变了:9.7.4 起服务端支持四段
MAJOR.MINOR.PATCH.UPDATE,而VERSION()仍返回三段。这条已在《MySQL 版本号变成四段,VERSION() 还返回三段》(/d/8188.html)里写过,本文不重复,只提醒巡检脚本和 CMDB 采集别被它绊住。
上线顺序建议
- 先跑上面三条查询,把 native 账号清单化,按「应用账号 / 复制账号 / 运维账号 / 只读报表账号」分组。
- 测试环境用同版本 connector 跑一遍完整认证路径,包括 TLS 与非 TLS 两种连接。
- 复制先升 replica 还是先升 source,按 9.7 的
replica_allow_higher_version_source决定;跨版本混跑窗口尽量短。 - 备份 + 验证恢复,确认逻辑备份能在 8.4 上导入,再动生产。
- 升级后立刻复查
mysql.user的 plugin 分布与 error log 里的认证失败记录。
没有 9.7.4 实例可测的部分(PBKDF2 存储格式的具体开关行为、ProxySQL 的兼容程度)都标了未实测,按贵司环境实测为准。