MySQL连接失败:2002、2003与1045排查
网站提示“数据库连接失败”,先保留错误码、完整文字和发生时间。2002、2003 通常要查连接路径,1045 要查认证;一上来重置密码,往往改不到真正的问题。
本文以 Linux 上的 MySQL 8.0、8.4 和 mysql 命令行为例。框架可能重新包装错误,判断时以完整提示为准。MariaDB 的账号表、认证插件和管理方式应按其自身版本核对,不能直接照搬本文的账号查询。
1. 先确定哪一条连接失败
从应用当前生效的配置中核对数据库地址、端口、用户名,以及应用是在服务器本机、Docker 容器还是另一台机器里运行。连接串可能含密码,只记录需要比较的字段。修改过配置文件,也要确认运行中的应用已经读取新值。
| 完整提示中的关键内容 | 优先检查 |
|---|---|
2002,并提到 socket 路径 |
本地 Unix socket 路径是否正确、服务是否运行、应用用户是否能访问该路径。 |
2003,并提到主机和端口 |
地址、端口、实际监听及两端之间的连接路径。 |
1045 Access denied |
先确认连的是目标实例,再核对账号、密码、客户端来源和认证方式。 |
1044 或 1049 |
1044 是访问指定数据库被拒绝;1049 是数据库名称不存在。分别检查库权限和库名,不要混成登录密码错误。 |
例如迁移后,应用地址仍指向旧数据库,就算账号和密码都没变,也可能报 1045。先核对目标地址,再继续下面的检查。
2. 在应用所在位置重做一次连接
在应用运行的 Linux 环境中执行测试。普通桥接网络的容器里,127.0.0.1 指向该容器自身;在宿主机测试成功,不能替代容器内的测试结果。
下面示范数据库就在当前环境、监听 TCP 3306 的情况。将 app_user 换成应用账号,地址和端口按实际配置替换;远程数据库沿用已配置的内网入口及 TLS、CA 验证参数。
mysql --protocol=TCP --host=127.0.0.1 --port=3306 --user=app_user --connect-timeout=5 -p
-p 后不写密码,出现提示后再输入,输入时不会显示字符。若提示 mysql: command not found,只是当前环境没有这个客户端或没有找到它,不能据此判断数据库服务离线。
在 Linux 上,localhost 默认可能走 Unix socket,指定端口也不一定改用 TCP;上面的 --protocol=TCP 用来明确本次测试方式。若应用原本使用 socket,仍需按第 3 步核对它的实际路径。
成功进入 mysql> 后执行:
SELECT 1;
SELECT VERSION(), @@hostname, USER(), CURRENT_USER();
quit
第一条应返回 1。第二条用于核对服务端版本、主机名及认证账号;CURRENT_USER() 是本次实际匹配到的 MySQL 账号。通过这一步只说明该连接能认证并执行简单查询,业务表权限还要用原应用验证。
3. 2002、2003:检查数据库所在端
在运行数据库的 Linux 环境中检查监听,端口不是 3306 时要替换。数据库在容器里时,应在对应容器网络环境中检查;宿主机看到的映射端口与容器内监听端口可能不同。
sudo ss -lntp 'sport = :3306'
sudo ss -lxnp
- 第一条没有输出:当前环境、指定端口未看到 TCP 监听,继续查实例状态及配置;不要先改密码。
- 只监听
127.0.0.1:3306:它只接收当前网络环境的本机连接,另一台机器不能直接通过服务器网卡地址访问这个监听。 - 第二条列出 Unix socket:找到数据库进程对应的路径,与应用报错里的路径比较。若服务没启动,socket 文件可能根本尚未创建。
如果实际路径是 /run/mysqld/mysqld.sock,可从同一环境明确指定 socket 测试;路径不同就先替换,不要照抄:
mysql --protocol=SOCKET --socket=/run/mysqld/mysqld.sock --user=app_user -p
路径正确仍报权限拒绝时,核对应用运行用户对 socket 及父目录的访问权限。删除 socket 文件、把目录权限统一改成 777,都不能代替找到权限问题。
使用 systemd 管理 MySQL 的服务器,可以检查实例状态和最近日志。以下以 mysql.service 为例;实际可能叫 mysqld.service 或其他名称,先按服务管理教程核对,再替换两行中的名称。
sudo systemctl status mysql.service --no-pager
sudo journalctl -u mysql.service --since '15 minutes ago' -n 80 --no-pager -o short-iso
刚复现的问题可查最近 15 分钟;旧故障按日志查询教程换成对应时间范围。面板管理的实例可能另有日志文件,日志为空不代表服务正常。记录启动失败原因,再处理配置、磁盘或权限问题。
若数据库端本地连接成功,应用端仍失败,再按端口排查教程检查两端路径。连接被拒绝时优先查端点和监听;连接超时还需核对网络规则与服务响应,不能仅凭超时认定某一层防火墙拦截。只需本机使用的数据库,无须为了排查开放公网 3306。
4. 1045:核对账号、来源与认证方式
using password: YES 只表示本次使用了密码,不表示密码正确;NO 表示本次没有使用密码。对照应用的当前配置检查账号和凭据,避免一直拿旧配置重试。
让有权限的数据库管理员,通过已有管理连接进入 mysql>,将下面的 app_user 换成出错的账号后查询:
SELECT User, Host, plugin, account_locked, password_expired
FROM mysql.user
WHERE User = 'app_user';
Host 限定客户端来源,不是数据库服务器的地址。同名用户、不同 Host 是不同账号,来源更具体的记录可能先被匹配。查到同名账号,不等于当前来源一定匹配了它。核对报错中数据库看到的客户端来源;成功连接后,可用 CURRENT_USER() 确认实际匹配结果。
查询同时列出认证插件、账号锁定和密码过期标记。普通应用账号无权查 mysql.user 很常见,不要为完成排查给它新增管理权限,也不要导出整张账号表。
若故障出现在升级之后,还要核对应用驱动版本。MySQL 8.4 默认禁用 mysql_native_password;使用该插件的旧账号可能无法登录。将实际插件和完整报错交给维护者,核对驱动兼容性并安排认证迁移。不要只为消除报错就降低认证或 TLS 要求。
5. 回到原应用确认恢复
使用原应用、原账号和原连接路径,重试之前失败的一次正常读取操作,并检查同一时间的日志。命令行成功而应用仍失败时,重点比较运行中的连接配置、容器位置和驱动版本;不要用管理账号替换业务账号来掩盖权限问题。
仍需协助时,提供发生时间、脱敏后的完整报错、应用与数据库各自运行位置、连接方式和端口、客户端与服务端版本,以及上面哪一步成功或失败。先按日志脱敏指南去掉密码、令牌和带凭据的连接串,再提交工单。
技术依据:MySQL 8.0、8.4 官方连接、错误码、账号与认证手册,Docker 网络文档,以及 ss、systemd 手册。核对日期:2026 年 11 月 4 日。