mysql 8.0双密码功能只能通过alter user ... identified by ... retain current password实现,set password不支持该语法且会清空辅助密码;需满足当前密码非空、插件为caching_sha2_password、版本≥8.0.14,并在主从同步完成后再切换应用,discard old password必须显式执行才能清理辅助密码。

MySQL 8.0 的双密码功能不能用 SET PASSWORD 配置,必须用 ALTER USER ... IDENTIFIED BY ... RETAIN CURRENT PASSWORD,否则旧密码立刻失效,业务连接会断。
为什么 SET PASSWORD 会破坏双密码
它根本不识别 RETAIN CURRENT PASSWORD 语法,执行后只会覆盖主密码,辅助密码被清空。常见错误现象包括:
- 执行
SET PASSWORD FOR 'u'@'h' = 'new'后,旧密码登录直接报ERROR 1045 (28000) - 脚本里混用
SET PASSWORD和ALTER USER,导致部分节点双密码生效、部分失效 - 误以为“只要密码能登就是双密码”,其实只是主密码单点生效,毫无过渡能力
ALTER USER ... RETAIN CURRENT PASSWORD 的硬性前提
这条语句不是“想用就用”,它依赖账户当前状态。不满足条件会直接报错:
-
ERROR 3031 (HY000): Cannot retain current password for account with empty password→ 账户当前authentication_string为空或为NULL,需先用ALTER USER ... IDENTIFIED BY设一个有效密码 - 用户插件不是
caching_sha2_password→ 双密码机制只在该认证插件下工作,可用SELECT plugin FROM mysql.user WHERE user = 'u' AND host = 'h'检查,不匹配则先执行ALTER USER 'u'@'h' IDENTIFIED WITH caching_sha2_password BY 'xxx' - MySQL 版本低于 8.0.14 → 该语法不存在,
SHOW VARIABLES LIKE 'version'必须确认
主从环境下的执行顺序和验证要点
在复制架构中,双密码切换不是主库一执行就完事。从库没同步完成前切应用,会有一批连接因“从库还不认新密码”而失败:
- 主库执行
ALTER USER 'u'@'h' IDENTIFIED BY 'new' RETAIN CURRENT PASSWORD后,立刻查SHOW SLAVE STATUS\G,等所有从库Seconds_Behind_Master = 0再推进 - 不要在事务里包裹该语句 ——
ALTER USER是隐式提交,事务控制无效,反而误导人以为能回滚 - 验证是否真双活:分别用新密码和旧密码连一次,都应成功;再查
mysql.user表,authentication_string字段值不变(仍是旧密码哈希),说明辅助密码已保留
DISCARD OLD PASSWORD 不是自动发生的
很多人以为“改十次密码后,最老那个自然过期”。事实是:只要没显式执行 DISCARD OLD PASSWORD,最早那次被 RETAIN CURRENT PASSWORD 保留下来的密码就永远有效。这既是灵活性,也是风险点:
- 审计时发现账户仍支持三年前的密码 → 很可能只是忘了执行
DISCARD OLD PASSWORD - 执行该语句后,
authentication_string字段会更新为新密码哈希,旧密码彻底不可用 - 没有“延迟清理”或“自动过期”机制,必须人工触发,且只能对当前主密码对应的辅助密码生效
真正容易被忽略的是:双密码机制完全不依赖时间窗口或有效期字段,它的“过渡期”由运维节奏决定——你通知应用方换密的速度,就是过渡期长度。别指望数据库替你计时或告警。











