ERROR 1396 (HY000)源于ALTER USER中用户名@主机名未完全匹配mysql.user表现有记录;须先查SELECT User,Host FROM mysql.user确认完整账户名,如'root'@'localhost'不可简写为'root'。

ALTER USER 修改密码策略时提示 ERROR 1396 (HY000)
这是最常见的权限或语法陷阱:MySQL 认为你要创建一个不存在的用户,而不是修改现有用户的密码策略。根本原因在于 ALTER USER 要求用户名和主机名(即 'user'@'host')必须**完全匹配**系统中已存在的 mysql.user 表记录。
实操建议:
- 先用
SELECT User, Host FROM mysql.user;确认目标用户的完整账户名,比如可能是'appuser'@'%'而非'appuser'@'localhost' - 如果只记得用户名,用
SELECT User, Host FROM mysql.user WHERE User = 'xxx';查准主机范围 - 避免省略
@'host'—— 即使是root,默认也常是'root'@'localhost'或'root'@'127.0.0.1',二者不等价 - 错误示例:
ALTER USER 'admin' IDENTIFIED BY 'newpass';→ 若实际账户是'admin'@'192.168.%',就会报 1396
批量设置多个用户的密码过期策略(PASSWORD EXPIRE)
PASSWORD EXPIRE 是最常用的安全策略之一,但 MySQL 不支持一条语句改多个用户,必须逐条执行。不过可以用生成 SQL 的方式“伪批量”处理。
实操建议:
- 查出所有需强制改密的用户(如 90 天未登录的):
SELECT CONCAT('ALTER USER ''', User, '''@''', Host, ''' PASSWORD EXPIRE;') AS stmt FROM mysql.user WHERE password_last_changed - 复制结果、粘贴执行 —— 注意检查生成的
Host是否合理,避免误锁'root'@'localhost' - 若想统一设为“永不过期”,用
PASSWORD EXPIRE NEVER;设为“下次登录强制改密”用PASSWORD EXPIRE DEFAULT - 注意:该策略仅对后续登录生效,已建立的连接不受影响
validate_password 插件启用后,ALTER USER 报错 “Failed to set password”
启用了 validate_password 插件后,ALTER USER ... IDENTIFIED BY 不再只校验语法,还会触发强度检查(长度、数字、大小写、特殊字符等)。失败时通常返回 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。
实操建议:
- 先查当前策略:
SHOW VARIABLES LIKE 'validate_password%';,重点关注validate_password.policy(0=LOW, 1=MEDIUM, 2=STRONG)和validate_password.length - 临时调低策略(仅调试用):
SET GLOBAL validate_password.policy = LOW;,但生产环境不建议长期关闭校验 - 更稳妥的做法是生成合规密码:
SELECT SHA2(RAND(), 256);或用外部工具生成含大小写字母+数字+符号的 12 位以上密码 - 插件默认不校验
ALTER USER ... REQUIRE SSL类语句,但一旦带IDENTIFIED BY就会触发
ALTER USER 后密码策略没生效?检查 authentication_string 和 plugin 字段
MySQL 8.0+ 默认使用 caching_sha2_password 插件,而旧客户端(如某些 PHP 7.4 扩展、老版 Navicat)可能不兼容。此时即使 ALTER USER 成功,用户仍无法登录,现象是报 ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded。
实操建议:
- 确认用户认证插件:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'xxx'; - 若需兼容旧客户端,显式指定插件:
ALTER USER 'xxx'@'yyy' IDENTIFIED WITH mysql_native_password BY 'strongpass'; - 注意:
authentication_string字段在 8.0+ 中由插件管理,不要手动 UPDATE 它 —— 这会导致密码失效且难以恢复 - 改完插件后,务必执行
FLUSH PRIVILEGES;(虽然多数情况自动刷新,但保险起见)
真正麻烦的不是命令怎么写,而是每个用户在 mysql.user 表里那行记录的 User、Host、plugin、password_last_changed 四个字段,任意一个对不上,ALTER USER 就会静默失败或报错。别信“我输的是用户名”,去表里查才是唯一可靠动作。


















