mysql 8.0+批量修改用户密码最有效方式是update mysql.user表的authentication_string字段并执行flush privileges,因alter user不支持变量或子查询;需注意认证插件、密码加密方式(推荐sha2)及host精确匹配。

直接用 UPDATE 语句改 mysql.user 表最有效
MySQL 8.0+ 不再支持 SET PASSWORD 或 UPDATE ... SET password=... 这类旧方式,必须用 ALTER USER 或更新 mysql.user 表的 authentication_string 字段。但批量改密码时,ALTER USER 不支持变量或子查询,所以最稳妥的做法是生成并执行 UPDATE + FLUSH PRIVILEGES。
注意:操作前必须有 UPDATE 权限且登录账户是 root 或具备 mysql.user 表写权限的高权限用户。
- 先确认当前认证插件:
SELECT user, host, plugin FROM mysql.user WHERE user IN ('u1', 'u2');,不同插件(如caching_sha2_passwordvsmysql_native_password)影响密码哈希方式 - 密码必须用
SHA2()或PASSWORD()(仅 5.7 兼容模式)加密,不能明文写入authentication_string - 改完必须执行
FLUSH PRIVILEGES,否则新密码不生效
批量生成 UPDATE 语句的可靠写法
别手敲多条 UPDATE,容易漏、错位、引号混乱。用 SELECT 拼出语句再复制执行:
SELECT CONCAT(
"UPDATE mysql.user SET authentication_string = PASSWORD('",
'newpass123',
"') WHERE user='", user, "' AND host='", host, "';"
) AS stmt
FROM mysql.user
WHERE user IN ('alice', 'bob', 'carol');
上面会输出三行 UPDATE 语句,每行对应一个用户。把结果复制进 MySQL 客户端逐条执行即可。
- 如果用户来自不同
host(比如'alice'@'localhost'和'alice'@'%'),WHERE条件里必须同时匹配user和host,否则误改 - MySQL 8.0.29+ 已废弃
PASSWORD(),建议改用SHA2('newpass123', 256),但注意这不会自动加盐,生产环境应优先走ALTER USER单条执行 - 避免在语句中拼接用户输入——此处只用于内部管理,切勿用于 Web 表单等不可信来源
用 ALTER USER 批量处理的变通方案
ALTER USER 本身不支持 IN 或列表,但可以靠 shell 脚本或客户端工具“循环执行”。例如在 Linux 终端用 mysql -e 配合 while:
echo "alice bob carol" | xargs -n1 | while read u; do mysql -uroot -p'xxx' -e "ALTER USER '$u'@'localhost' IDENTIFIED BY 'newpass123';" done
这种方式更安全(自动调用认证逻辑,兼容插件和过期策略),但要求每个用户 host 明确且可枚举。
- 如果用户 host 不统一(有的是
%,有的是 IP),得先查出完整user@host对,再构造循环 -
ALTER USER会触发密码历史检查、强度验证等策略,若失败会中断,需捕获ERROR 1819等提示 - MySQL 5.7 不支持
ALTER USER ... IDENTIFIED WITH指定插件,升级前请核对版本
改完连不上?重点检查这三处
常见报错 Access denied for user 或 Client does not support authentication protocol,基本不是密码错,而是上下文不匹配:
- 客户端用的是老驱动(如 MySQL Connector/J 5.x),连 8.0+ 的
caching_sha2_password用户时会握手失败——换驱动或改用户插件:ALTER USER 'u'@'h' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 忘了
FLUSH PRIVILEGES,尤其用UPDATE直接改表后,缓存未刷新 - 连接时用了错误的
host,比如用户是'u'@'192.168.%',但你用localhost连,实际匹配到的是'u'@'localhost'这个不同记录
真正麻烦的从来不是怎么改密码,而是改完之后谁在哪个 host 上用什么插件连、用什么客户端版本连——这些细节不列清楚,批量操作等于埋雷。











