在 MySQL 5.7.6 及以上版本中,修改其他用户密码的官方推荐操作路径是 ALTER USER。相比直接修改 mysql.user 表或使用 PASSWORD() 函数,这种方式更安全、更规范,并且会自动刷新权限,省去了手动执行 FLUSH PRIVILEGES 的步骤。不过,它有一些硬性门槛:你需要拥有 CREATE USER 或 UPDATE 权限;目标用户不能是系统保留账户(如 mysql.infoschema、mysql.session),否则会报错 ERROR 1396 (HY000)。此外,host 必须精确匹配——'user'@'localhost' 和 'user'@'127.0.0.1' 是两个完全不同的账户,查不到就会报错。密码还必须符合 validate_password 策略,否则无法通过。

ALTER USER 是唯一推荐的密码修改方式
从 MySQL 5.7.6 开始,直接更新 mysql.user 表已被禁止,PASSWORD() 函数也被废弃。官方唯一推荐的正规途径就是 ALTER USER——它会自动刷新权限表,无需手动执行 FLUSH PRIVILEGES,也完全不用担心字段名变化(例如从 password 改为 authentication_string)导致脚本崩溃。
但执行 ALTER USER 需要满足两个前提:第一,你必须拥有 CREATE USER 权限,或者对 mysql 库的 UPDATE 权限;第二,目标用户不能是系统保留账户(比如 mysql.infoschema、mysql.session),否则会遇到熟悉的 ERROR 1396 (HY000)。
ALTER USER 'app_user'@'192.168.1.100' IDENTIFIED BY 'P@ssw0rd2026!';- 主机名必须精确匹配:
'app_user'@'localhost'不等于'app_user'@'127.0.0.1',如果找不到用户,会直接报错 - 如果用户不存在,请先用
CREATE USER创建账户,再通过ALTER USER设置密码
SET PASSWORD 已退居次要地位,使用时需谨慎
SET PASSWORD FOR 在 MySQL 8.0+ 中仍然可用,但仅限于拥有 UPDATE 权限的用户操作,而且不再支持 PASSWORD() 函数——直接传入明文密码即可:
SET PASSWORD FOR 'reporter'@'%' = 'N3wR3p0rtP@ss!';- 如果是 MySQL 5.7.5 及更早版本,才支持
= PASSWORD('xxx')写法,新版这样写会报ERROR 1064 - 这条语句不会自动刷新权限表,执行后必须立即跟上
FLUSH PRIVILEGES;,否则新密码不会生效 - 不建议在自动化脚本中使用,因为它在不同小版本之间的行为并不稳定
validate_password 插件常导致 ERROR 1819
默认情况下,该插件是开启的。如果密码不满足策略要求,ALTER USER 会直接失败,并提示 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。
先检查当前的策略级别:SELECT @@validate_password.policy;(0 代表 LOW,1 代表 MEDIUM,2 代表 STRONG)
- MEDIUM 级别要求:密码长度 ≥ 8,并且包含大小写字母、数字、特殊字符
- 如果只是在调试环境临时绕过,可以执行
SET GLOBAL validate_password.policy = LOW;,但生产环境中千万别这么做 - 避免使用纯数字、常见单词或重复字符,例如
12345678、password123
mysqladmin 不适合修改其他用户密码
mysqladmin -u root -p password 'new' 这个命令只能修改当前连接用户的密码(即 USER() 函数返回的账户),无法指定目标账号。如果试图用它修改 app_user 的密码,实际上修改的是你登录时所用的账户——比如 root,这是典型的误用场景。
它本质上是封装了 SET PASSWORD = 'xxx',仅作用于当前会话上下文。
- 要批量修改多个用户的密码?还是老老实实进入 MySQL 客户端,逐条执行
ALTER USER - 在脚本中调用
mysqladmin之前,务必确认-u指定的正是你要修改密码的那个用户本身 - 它不校验 host,也不处理 validate_password,很容易隐藏真正的问题
实际操作中最容易忽略的,就是 host 字符串的精确性。'user'@'localhost' 和 'user'@'%' 是两个完全独立的账户,权限、密码甚至是否启用都互不影响。连错了 host,即使语法完全正确,也会提示用户不存在——这个坑,不少人都踩过。
