必须用alter user 'user'@'host' password expire;才能触发强制改密,因set password仅更新密码哈希而不修改password_expired字段,mysql的过期逻辑由元数据驱动;前提为用户存在、执行者有alter user权限、且@@default_password_lifetime≠0。

直接用 ALTER USER 'user'@'host' PASSWORD EXPIRE; 就行,但必须满足三个前提:用户存在、执行者有 ALTER USER 权限、且 @@default_password_lifetime 不为 0。
为什么 SET PASSWORD 不会触发强制改密
SET PASSWORD FOR 'u'@'h' = 'xxx'; 只更新密码哈希值,完全不修改 mysql.user 表里的 password_expired 字段。MySQL 的强制改密逻辑是元数据驱动的,和密码本身无关——哪怕你刚设了新密码,只要没显式标记过期,登录时就不会拦截。
- 错误写法:
SET PASSWORD FOR 'alice'@'localhost' = 'new123'; ALTER USER 'alice'@'localhost' PASSWORD EXPIRE;—— 两步分离,中间若被其他操作中断,第二步容易漏掉 - 正确写法(一步到位):
ALTER USER 'alice'@'localhost' IDENTIFIED BY 'new123' PASSWORD EXPIRE; - 如果只想标记过期、不改密码,就只用
ALTER USER 'alice'@'localhost' PASSWORD EXPIRE;,别混用IDENTIFIED BY
用户登录后没报 ERROR 1820?检查这三点
设了 PASSWORD EXPIRE 却仍能正常执行 SELECT,大概率是以下某个条件成立:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 该用户拥有
ALTER USER权限:MySQL 允许有此权限的用户跳过强制重置流程 - 服务器全局关闭了过期机制:
SELECT @@default_password_lifetime;返回 0,此时所有PASSWORD EXPIRE都无效 - 客户端连接时自动执行了
SET NAMES utf8mb4等非业务语句,但还没发第一条SELECT或SHOW——ERROR 1820要等到首个非SET类语句才触发
PASSWORD EXPIRE NOW 和 INTERVAL N DAY 的实际区别
两者都把 password_expired 设为 'Y',但后续行为不同:
-
PASSWORD EXPIRE NOW:立即生效,下次登录认证成功后,首次执行非SET语句即报错 -
PASSWORD EXPIRE INTERVAL 60 DAY:不是“60 天后才开始限制”,而是从password_last_changed时间点起算 60 天;若当前已超期,效果等同于NOW - 查是否真超期,不能只看
password_expired字段,得结合:SELECT user, host, password_last_changed, TIMESTAMPADD(DAY, @@default_password_lifetime, password_last_changed) AS expires_at FROM mysql.user WHERE user = 'alice';
最容易被忽略的是:PASSWORD EXPIRE 对已有活跃连接无影响,只作用于新登录;且无法通过 mysql -u alice -p 的交互式输入绕过——错误在服务端认证后、授权前就返回了,根本不会走到 SQL 执行阶段。










