mysql 8.0 不支持自动密码轮转,仅提供双密码机制(8.0.14+)实现无缝切换:通过 retain current password 同时启用主、辅密码,旧连接不受影响;待应用迁移完成后,再用 discard old password 清理旧密码,全过程需外部调度驱动。

MySQL 8.0 本身不提供“自动密码轮转”功能——没有后台定时任务、没有配置项开关、也没有内置调度器能帮你定期改密码。所谓“自动”,必须靠外部系统驱动,而 MySQL 只负责支持安全、无中断的切换能力,核心就是 RETAIN CURRENT PASSWORD 和 DISCARD OLD PASSWORD 这两个机制。
为什么 ALTER USER ... IDENTIFIED BY 不等于自动轮转
直接执行 ALTER USER 'u'@'h' IDENTIFIED BY 'new' 会立刻覆盖旧密码,所有还在用旧密码的连接会在下次认证时失败(比如连接池重连、应用重启),导致业务中断。这不是轮转,是硬切换。
- 它不保留旧凭证,无法兼容存量连接
- 它不记录密码变更历史,无法审计“何时启用了新密码”
- 它不区分主/辅角色,后续再改密码时无法基于“当前主密码”做链式更新
双密码机制是轮转的前提,但需手动触发
真正支撑无缝轮转的是 MySQL 8.0.14+ 的双密码能力,但它完全依赖 DBA 或运维脚本显式调用,不是自动发生的。
- 启用共存:执行
ALTER USER 'u'@'h' IDENTIFIED BY 'new_pass' RETAIN CURRENT PASSWORD—— 此时新密码为主,旧密码为辅,两者都可登录 - 验证过渡期:需外部监控确认所有应用已使用新密码建连(例如查
performance_schema.threads的认证用户、或日志分析) - 清理旧密码:确认无残留后,执行
ALTER USER 'u'@'h' DISCARD OLD PASSWORD—— 辅助密码被彻底删除
注意:RETAIN CURRENT PASSWORD 要求当前会话已用旧密码成功认证;若用新密码登录后再执行该语句,会报错 ER_CANT_RETAIN_CURRENT_PASSWORD。
如何模拟“自动”轮转:三步外部编排
真正的自动化必须由外部调度器(如 cron、systemd timer、Airflow、K8s CronJob)驱动,并配合状态检查逻辑:
- 第一步:在预定时间点执行双密码切换 SQL(如通过
mysql -u root -e "ALTER USER ... RETAIN CURRENT PASSWORD") - 第二步:等待足够长的宽限期(例如 24–72 小时),期间轮询检查应用连接是否已全部迁移到新密码(可通过查询
information_schema.PROCESSLIST中的USER字段,或结合应用层埋点) - 第三步:宽限期结束后,执行
DISCARD OLD PASSWORD;若发现仍有旧密码连接,则中止流程并告警
关键细节:MySQL 不暴露“哪个密码被用于本次连接”的字段,所以不能直接从服务端判断某条连接用的是主还是辅密码——只能靠应用侧主动上报,或依赖连接池配置统一更新的时间窗口来推断。
容易被忽略的兼容性陷阱
双密码机制看似简单,但实际落地常卡在客户端和中间件上:
- 老版本 MySQL Connector/J(Access denied,即使密码正确
- 某些连接池(如 HikariCP 默认配置)启用
connection-test-query时,若测试语句在密码切换窗口中执行,可能因认证插件协商失败而清空整个连接池 -
caching_sha2_password插件下,客户端首次连接需 RSA 密钥交换;若服务端未配sha256_password_auto_generate_rsa_keys=ON且未预置密钥文件,双密码切换后部分客户端会静默失败
最稳妥的做法:升级所有客户端驱动到 8.0.16+,并在切换前确认 SELECT @@default_authentication_plugin 返回值,必要时对用户显式指定插件:ALTER USER 'u'@'h' IDENTIFIED WITH caching_sha2_password BY 'p' RETAIN CURRENT PASSWORD。











