MySQL 8.0.14+ 支持双密码机制实现零中断密码切换:先用 ALTER USER ... IDENTIFIED BY 'new' RETAIN CURRENT PASSWORD 同时启用主、辅密码,待应用全部迁移后,再执行 DISCARD OLD PASSWORD 彻底清除旧密码。

MySQL 8.0.14+ 才能真正“不中断业务”改密码,靠的是双密码机制;低于这个版本,所有改密码操作都会断连。
ALTER USER ... RETAIN CURRENT PASSWORD 是唯一安全切换路径
这是 MySQL 8.0.14 引入的语法,不是可选技巧,而是实现零中断的必要条件。它让主密码(新)和辅助密码(旧)同时生效,现有连接继续用旧密码维持,新连接可用任一密码登录。
- 必须显式指定完整用户标识,比如
'app_user'@'10.20.30.%',不能只写'app_user' - 执行后无需
FLUSH PRIVILEGES,权限立即生效 - 旧密码不会自动过期,也不会被覆盖——它作为辅助密码被保留,直到你主动丢弃
- 如果误删了辅助密码(比如先执行了
DISCARD OLD PASSWORD),而应用还没切新密码,就会立刻报错Access denied for user
DISCARD OLD PASSWORD 不是“清理动作”,而是关键业务确认点
这步不是技术收尾,而是运维确认:所有应用配置、连接池、脚本、监控探针都已更新完毕,且持续稳定运行至少一个观察周期(建议 24 小时以上)。一旦执行,旧密码立刻失效。
- 执行前务必确认:所有客户端使用的 MySQL 连接库支持
caching_sha2_password(如 mysql-connector-python 8.0.23+、JDBC 8.0.28+) - 若仍有老客户端(如 Navicat 15 以下、某些 PHP mysqli 扩展),需提前改用
mysql_native_password插件,否则即使密码正确也会报Authentication plugin 'caching_sha2_password' cannot be loaded -
DISCARD OLD PASSWORD不接受参数,也不支持回滚;执行即永久移除辅助密码
低于 8.0.14 的版本根本做不到“不中断”
所有所谓“平滑过渡”的变通方案(比如先建新用户再切流量、用代理层做密码映射)都是绕开 MySQL 原生能力的临时补丁,本质仍是业务侧承担风险。MySQL 自身不提供双密码支持,ALTER USER 或 SET PASSWORD 都会立即覆盖旧凭证。
-
UPDATE mysql.user SET authentication_string = ...在 8.0+ 会导致认证插件错乱,连接直接失败 -
SET PASSWORD FOR ... = PASSWORD('x')在 8.0+ 语法错误,因为PASSWORD()函数已被彻底移除 - 用
mysqladmin -u root -p password 'new'看似命令行无感,但后台仍是原子覆盖,正在使用的连接会在下次认证时(如连接池重连)失败
真正容易被忽略的点是:双密码机制只管“密码验证”,不管“连接状态”。如果应用使用长连接且未设置 wait_timeout 自动回收,旧连接可能存活数小时甚至数天——这不是 bug,而是设计使然。你要盯的不是 SQL 执行成功与否,而是所有客户端是否完成配置更新并触发过至少一次新连接。


















