编程 MySQL 9.7 升级前先清账号:native_password 在 9.0 就没了,原地回滚也不行

2026-10-28 00:05:38

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 或更早不支持。

推论是三条工程约束:

  1. 升级前必须有可验证的逻辑备份(mysqldump / MySQL Shell dump),或者留一台 8.4 的旧实例做复制回切,别指望「换回二进制重启」。
  2. 升级后一旦用了 9.7 独有特性(例如 9.7 的 masking policy、JSON Duality View 的 DML),跨系列回滚就不成立了,只能从升级前备份恢复。
  3. 应用侧要能回到 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 采集别被它绊住。

上线顺序建议

  1. 先跑上面三条查询,把 native 账号清单化,按「应用账号 / 复制账号 / 运维账号 / 只读报表账号」分组。
  2. 测试环境用同版本 connector 跑一遍完整认证路径,包括 TLS 与非 TLS 两种连接。
  3. 复制先升 replica 还是先升 source,按 9.7 的 replica_allow_higher_version_source 决定;跨版本混跑窗口尽量短。
  4. 备份 + 验证恢复,确认逻辑备份能在 8.4 上导入,再动生产。
  5. 升级后立刻复查 mysql.user 的 plugin 分布与 error log 里的认证失败记录。

没有 9.7.4 实例可测的部分(PBKDF2 存储格式的具体开关行为、ProxySQL 的兼容程度)都标了未实测,按贵司环境实测为准。

推荐文章

程序员茄子在线接单