必须用 ALTER USER ... IDENTIFIED BY ... RETAIN CURRENT PASSWORD 实现双密码,因 SET PASSWORD 仅写主密码且强制清空辅助密码,导致连接中断;该语句要求 authentication_string 非空、插件为 caching_sha2_password、MySQL ≥ 8.0.14、仅主库执行,并需主从同步完成后再切应用,旧密码需显式 DISCARD OLD PASSWORD 才清理。

必须用 ALTER USER ... IDENTIFIED BY ... RETAIN CURRENT PASSWORD,其他任何方式(尤其是 SET PASSWORD)都会清空旧密码、导致连接中断。
为什么不能用 SET PASSWORD
SET PASSWORD 在 MySQL 8.0 中完全不参与双密码机制。它只写主密码,且强制清空辅助密码——哪怕你刚用 RETAIN CURRENT PASSWORD 设好双密码,下一条 SET PASSWORD 就会让旧密码立即失效。
- 执行
SET PASSWORD FOR 'u'@'h' = 'new'后,应用连接会随机断开(取决于主从同步进度) - 混写
SET PASSWORD ... RETAIN CURRENT PASSWORD直接报语法错误:ERROR 1064 (42000) - 误以为“设两次密码=双密码”,实际只是反复覆盖主密码,辅助密码从未被创建
ALTER USER ... RETAIN CURRENT PASSWORD 的硬性前提
这条语句看似简单,但任意一个条件不满足就会报错,常见失败点集中在账户状态和环境上:
-
authentication_string字段不能为NULL或空字符串:先查SELECT authentication_string FROM mysql.user WHERE user = 'u' AND host = 'h',为空则需先用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(生产建议 ≥ 8.0.23):
SHOW VARIABLES LIKE 'version'确认 - 只能在主库执行;从库未同步完成前切应用,会出现部分节点认新密码、部分只认旧密码的
Access denied
主从环境下执行顺序与验证要点
双密码切换不是主库一执行就完事,必须确保复制已收敛:
- 主库执行
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不是自动触发的——改十次密码后,最早那次被RETAIN CURRENT PASSWORD保留下来的密码仍有效,必须显式执行ALTER USER 'u'@'h' DISCARD OLD PASSWORD才能清理
最容易被忽略的是:双密码不会过期,也不会随改密次数自动清理。漏掉 DISCARD OLD PASSWORD,半年前的密码仍能登录——安全审计时发现这类问题,八成是这一步没做。


















