error 1045 根本原因不是密码错误,而是 mysql.user 表中缺失 'root'@'localhost' 记录、host 匹配失败、plugin(如 caching_sha2_password 或 auth_socket)不兼容或权限禁用;必须查 host/user/authentication_string/plugin 四字段确认实际配置。

直接说结论:ERROR 1045 不是密码输错了就重设密码,而是 MySQL 在 user 表里根本没找到匹配的 'root'@'localhost' 记录,或者该记录权限被禁用、认证插件不兼容。重点查 mysql.user 表里的 host、user、authentication_string 和 plugin 四个字段。
确认 root@localhost 是否真实存在
很多情况下,你认为自己在用 root@localhost 登录,但 MySQL 实际只认 root@127.0.0.1 或 root@'%' —— 而这两者在权限表里是完全不同的行。必须先验证是否存在对应记录:
- 如果还能用其他账号(比如有 sudo 权限的系统用户)进 MySQL,执行:
SELECT host, user, authentication_string, plugin FROM mysql.user WHERE user = 'root';
- 若返回空或只有
root@'%',说明root@localhost这条记录缺失或被删了 - 特别注意:MySQL 8.0+ 默认不再自动创建
root@localhost,安装后只留root@'localhost'的情况反而少见;有些一键脚本或 Docker 镜像甚至只建了root@127.0.0.1
检查 host 匹配是否被更宽泛规则覆盖
MySQL 用户匹配顺序是严格按 host 字段排序的:越具体的 host(如 localhost)优先级越高,但若配置了 skip-name-resolve,localhost 可能被解析成 127.0.0.1,导致匹配到另一条记录。
- 执行
SELECT host, user FROM mysql.user ORDER BY host DESC, user;
观察排序结果 —— 注意'%'排最前,'localhost'排最后,但 MySQL 实际匹配时会选「最精确匹配」,不是按这个顺序执行 - 如果你用
mysql -u root -h 127.0.0.1 -p能登录,但mysql -u root -h localhost -p报 1045,大概率是localhost走的是 socket 连接,而 user 表里没有root@localhost这条记录(socket 连接强制匹配host='localhost') - 临时验证方式:加
--protocol=tcp强制走 TCP:mysql -u root -h localhost -p --protocol=tcp
,如果这时能进,说明问题出在 socket + host='localhost' 的组合上
验证 plugin 是否导致认证失败
MySQL 5.7 默认用 mysql_native_password,MySQL 8.0+ 默认改用 caching_sha2_password。老客户端(如旧版 Navicat、PHP mysqli 扩展、某些 Python 驱动)不支持后者,就会静默失败并报 1045(不是提示“不支持插件”,而是直接拒绝)。
- 查当前 root@localhost 的插件:
SELECT plugin FROM mysql.user WHERE user='root' AND host='localhost';
- 如果是
caching_sha2_password且你无法升级客户端,可降级为兼容模式:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
- 注意:不能只改 password 字段,必须用
IDENTIFIED WITH显式指定插件,否则 MySQL 8 仍会沿用默认插件
权限字段为空或 plugin 为 auth_socket 时的典型表现
某些 Linux 发行版(如 Ubuntu)的 MySQL 包默认把 root@localhost 的 plugin 设为 auth_socket,它不校验密码,而是检查系统用户是否为 mysql。此时即使输对密码也会报 1045(using password: YES)。
- 查 plugin 值:
SELECT user, host, plugin FROM mysql.user WHERE user='root' AND host='localhost';
- 若 plugin 是
auth_socket,且你不想切系统用户登录,就换回密码认证:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
- 反过来,如果 plugin 是
auth_socket却又想免密登录,应使用sudo mysql -u root(不加-p),靠系统身份透传
真正卡住人的地方,往往不是密码记错,而是 host 字段的语义差异、socket/TCP 连接路径分歧、以及 plugin 和客户端能力之间的隐式不兼容 —— 这些不会在错误信息里明说,得进 mysql.user 表亲手翻四列数据才能定位。











