彻底解决 MySQL 报错 ERROR 1045 (28000): Access denied for user

详细排查并彻底解决 MySQL ERROR 1045 (28000): Access denied for user 访问被拒绝错误,包含密码重置、主机授权与权限刷新步骤。

发布于

在使用 MySQL 命令行、Navicat、DBeaver 或后端程序连接 MySQL 数据库时,最常遇到的权限报错就是 ERROR 1045 (28000):

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

或者:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

本文将详细分析导致该错误的 4 种核心原因,并给出在 Windows 和 Linux/macOS 环境下的快速排查与终极修复方案。

错误原因深度剖析

ERROR 1045 本质是 MySQL 服务器在握手认证阶段拒绝了客户端的连接请求。错误提示中的关键信息包括:

  • user: 登录时使用的用户名。
  • host: 客户端发起的 IP 或主机来源(例如 localhost、127.0.0.1 或局域网 IP)。
  • using password: YES 表示你输入了密码但密码不匹配;NO 表示未提供密码。

常见诱因:

  1. 密码输入错误:包含密码包含特殊字符被 Shell 转义、大小写混淆或初始随机密码未正确更新。
  2. 主机限制(Host 不匹配):MySQL 用户是由 用户名@主机 唯一定义的。例如 root@localhost 允许本机登录,但不允许来自远程 IP 或 Docker 宿主机的连接。
  3. 认证插件(Authentication Plugin)不兼容:MySQL 8.0 默认使用 caching_sha2_password 插件,而旧版客户端仅支持 mysql_native_password。
  4. 权限未刷新:通过直接修改 mysql.user 表而非 GRANT 语句赋予权限,未执行 FLUSH PRIVILEGES;。

解决方案一:通过安全模式跳过授权表重置密码

如果你完全忘记了 root 密码,可以通过跳过权限表(--skip-grant-tables)方式重置。

步骤 1:停止 MySQL 服务

在 Linux 系统执行:

sudo systemctl stop mysql
# 或 CentOS / Rocky Linux:
sudo systemctl stop mysqld

在 Windows 系统执行(以管理员权限打开 CMD):

net stop mysql

步骤 2:以安全模式启动 MySQL

在 Linux 终端执行:

sudo mysqld_safe --skip-grant-tables --skip-networking &

在 Windows 终端执行:

mysqld --console --skip-grant-tables --shared-memory

[!NOTE] 添加 --skip-networking 参数可以禁止网络远程连接,确保在免密维护期间外部流量无法入侵。

步骤 3:免密登录并修改密码

新打开一个终端窗口,直接输入 mysql 登录:

mysql -u root

成功进入 MySQL 交互式控制台后,根据你的 MySQL 版本执行重置语句:

对于 MySQL 8.0 及以上版本:

FLUSH PRIVILEGES;

-- 将密码重置为您自己的强密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourNewPassword123!';

FLUSH PRIVILEGES;

[!TIP] 如果你的客户端驱动较新,推荐保留默认的 caching_sha2_password: ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewPassword123!';

对于 MySQL 5.7 版本:

FLUSH PRIVILEGES;

ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewPassword123!';

FLUSH PRIVILEGES;

步骤 4:重启 MySQL 恢复正常认证

退出 MySQL 客户端并杀掉安全模式进程:

exit;

在 Linux 上重启服务:

sudo pkill mysqld
sudo systemctl start mysql

在 Windows 上重启服务:

net start mysql

现在使用新密码登录即可正常进入:

mysql -u root -p

解决方案二:排查远程连接与 Host 授权

如果你可以在服务器本地通过 localhost 登录,但使用 Navicat、DBeaver 等客户端在另一台机器连接时提示 ERROR 1045,则是由于用户缺少远程主机连接权限。

步骤 1:检查现有用户的 Host 列表

登录到 MySQL 命令行,查询 mysql.user 表:

SELECT user, host, plugin FROM mysql.user;

输出示例:

+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| root             | localhost | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+

可以看到 root 仅允许从 localhost 登录。

步骤 2:修改 Host 允许任意主机或特定局域网

执行以下命令允许 root 从任意 IP 地址访问:

-- 方式 A: 修改已有 root 的 host 为 %
UPDATE mysql.user SET host = '%' WHERE user = 'root' AND host = 'localhost';

-- 方式 B: 或者新建一个专门供远程访问的专用管理员账号(更安全)
CREATE USER 'admin'@'%' IDENTIFIED BY 'YourStrongPassword123!';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;

-- 必须刷新权限生效
FLUSH PRIVILEGES;

解决方案三:解决客户端与 MySQL 8.0 认证插件不兼容

若连接时报错附带 Client does not support authentication protocol requested by server,说明连接工具(如老版本 Navicat、旧版 JDBC 驱动或 Node.js mysql 包)不支持 MySQL 8.0 的 caching_sha2_password 算法。

只需将该用户的认证插件切换为兼容模式 mysql_native_password:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'YourNewPassword123!';
FLUSH PRIVILEGES;

总结与生产环境避坑指南

  1. 避免在生产环境中将 root 的 host 设为 %:建议针对应用创建独立账号(如 app_user),并限制其只对业务数据库具备读写权限。
  2. 每次修改 mysql.user 表必须执行 FLUSH PRIVILEGES;:通过 ALTER USER 或 GRANT 语句修改会自动刷新,但直接执行 UPDATE 时必须手动刷新。
  3. 密码包含特殊字符的终端转义:在 Linux 终端执行 mysql -u root -p'P@ss!123' 时,! 会被 Bash 解释为历史扩展命令,导致密码错乱。建议直接使用 mysql -u root -p,回车后在隐蔽提示下键入密码。