90%的access denied错误源于host不匹配、认证插件不兼容或grant option缺失;需先查select user,host from mysql.user确认报错中'user'@'host'是否精确存在,再按需创建账号、alter user指定mysql_native_password插件并赋予grant option权限。

90% 的 Access denied for user 错误,根本不是密码错,而是 host 不匹配、认证插件不兼容、或缺少 GRANT OPTION —— 三者常叠加出现,单查密码只会绕远路。
看报错里的 'user'@'host' 是否真实存在
MySQL 把 'root'@'localhost' 和 'root'@'127.0.0.1' 当作两个完全独立账号。错误信息里写的 host,就是你要对准的目标。
- 连的时候用的是
mysql -h 127.0.0.1 -u root -p,但SELECT User, Host FROM mysql.user WHERE User = 'root';只返回root@localhost?那必然失败 - 执行
SELECT User, Host FROM mysql.user WHERE User = 'root';,逐行比对输出,确认有没有和报错中一模一样的Host值 - 若缺失,补一个:例如
CREATE USER 'root'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY '你的密码'; - 别漏授权:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;,然后FLUSH PRIVILEGES;
检查并修正认证插件(尤其 MySQL 5.7+)
MySQL 5.7 起默认用 caching_sha2_password,但老版本 PHP、Python MySQLdb、DBeaver 旧版、某些监控工具只认 mysql_native_password。密码完全正确也会报 Access denied。
- 进库后查当前插件:
SELECT plugin FROM mysql.user WHERE User = 'root' AND Host = 'localhost'; - 如果不是
mysql_native_password,强制改:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; - 严禁用
UPDATE mysql.user SET authentication_string = ...—— 字段已废弃,且不会生效 - 改完立刻执行
FLUSH PRIVILEGES;,否则新设置不加载
确认你自己有没有 GRANT OPTION
MySQL 8.0+ 默认不给 root@localhost 自带 WITH GRANT OPTION。你用 root 登录了,不代表你能给别人授权 —— GRANT 命令会静默失败或报 Access denied。
- 查自己权限:
SHOW GRANTS FOR CURRENT_USER();,重点看输出里有没有WITH GRANT OPTION - 没有就补:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; - 注意:MySQL 8.0+ 不允许在
GRANT语句里写IDENTIFIED BY,必须拆成CREATE USER+GRANT两步
区分 ERROR 1045 和 ERROR 1142
这两个错误阶段完全不同,混在一起查会浪费大量时间。
-
ERROR 1045 (28000)是登录认证失败,属于连接阶段问题 —— 查mysql.user表的User、Host、plugin、authentication_string -
ERROR 1142是登录成功后操作被拒,说明已进库但权限不足 —— 运行SHOW GRANTS FOR 'u1'@'%';看实际分配的权限,注意USAGE只代表能连,不代表能查表 - 远程连接时,即使权限全开,若
my.cnf中bind-address = 127.0.0.1或防火墙没放行 3306,也会表现为Access denied
最易被忽略的点是:同一个用户名在不同 Host 下是独立账户;GRANT 后不 FLUSH PRIVILEGES 在某些配置下仍不生效;以及 CURRENT_USER() 和 USER() 返回值可能不一致 —— 这三个细节一错,排查方向就全偏了。











