error 1820 表示密码过期需用 alter user 重置,且该语句必须是登录后唯一首条命令;host 必须匹配(如 'root'@'localhost' 或 'root'@'%'),set password 无效,无需 flush privileges。

执行ALTER USER后仍报错ERROR 1820怎么办
这是最常被忽略的环节:MySQL在密码过期状态下进入的是“受限会话模式”,ALTER USER语句本身必须是**第一条且唯一允许执行的语句**,后续任何其他语句(包括SELECT、USE、甚至再次ALTER USER)都会触发ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement。
常见错误操作包括:
- 登录后先执行
USE mysql再改密 → 直接报错 - 执行
ALTER USER ... IDENTIFIED BY 'xxx'后,顺手敲了FLUSH PRIVILEGES→ 报错 - 用旧密码登录后,在同一连接里反复执行
ALTER USER(比如试了两次不同密码)→ 第二次就失败
正确做法是:登录后**不执行任何其他命令**,直接一条ALTER USER完成重置,然后退出重连。不需要FLUSH PRIVILEGES——MySQL 8.0+ 的权限变更已自动生效。
ALTER USER语法中host不匹配导致失败
报错ERROR 1396 (HY000): Operation ALTER USER failed for 'root'@'localhost'或类似提示,往往不是密码问题,而是host值写错了。MySQL用户是(user, host)二元组,'root'@'localhost'和'root'@'%'是两个完全不同的账户。
查准当前用户的真实host:
- 如果能登录(比如用跳过验证方式),运行:
SELECT user, host FROM mysql.user WHERE user = 'root'; - 注意:Windows下默认安装可能创建的是
'root'@'127.0.0.1'或'root'@'::1'(IPv6),而非'localhost' - 若不确定,可临时用通配符:
ALTER USER 'root'@'%' IDENTIFIED BY 'NewPass123!';(仅限测试环境,生产慎用)
为什么SET PASSWORD不生效,必须用ALTER USER
MySQL 8.0+ 废弃了SET PASSWORD对过期用户的重置能力。即使语法没错,执行SET PASSWORD = PASSWORD('xxx')也会返回成功,但实际密码未更新,下次登录仍提示过期。
根本原因是:密码过期状态由password_expired字段控制,而SET PASSWORD只更新authentication_string,不重置该标志位;只有ALTER USER ... IDENTIFIED BY会同时更新密码哈希并清除过期标记。
所以不要尝试这些无效写法:
SET PASSWORD FOR 'root'@'localhost' = 'xxx';-
UPDATE mysql.user SET authentication_string = ...(手动更新系统表会破坏一致性,且8.0+不再支持PASSWORD()函数)
ALTER USER后连接池仍连不上?检查客户端兼容性
应用重启后仍报ERROR 1862 (HY000): Your password has expired,大概率是连接池缓存了旧连接或未启用过期密码支持。
关键点:
- JDBC驱动需≥8.0.19,且URL中必须显式加
allowPublicKeyRetrieval=true(否则RSA密钥交换失败,被误判为过期) - Python
pymysql需≥1.0.2,mysql-connector-python需≥8.0.23 - 连接池(如HikariCP、Druid)要配置
connection-test-query或启用test-on-borrow,避免复用已断开的过期连接 - 某些老版本客户端(如早期Navicat)根本不支持过期密码握手流程,会直接拒绝连接
真正容易被忽略的是:ALTER USER只解决服务端状态,客户端是否能“顺利走完过期密码重置握手”,取决于它是否实现了MySQL协议里的auth_switch_request流程——很多轻量级驱动压根没实现。











