“sqlstate[hy000] [2002] connection refused”表明pdo连接被操作系统或mysql服务拒绝,需依pdoexception message定位:服务未启动、端口未监听、防火墙拦截、hostname解析错位或socket路径不匹配。
![thinkphp数据库配置实战:解决“sqlstate[hy000] [2002] connection refused”的常见排查思路](https://img.php.cn/upload/article/001/503/042/178001090779846.png?x-oss-process=image/resize,p_40)
“SQLSTATE[HY000] [2002] Connection refused”不是 ThinkPHP 的 bug,而是 PDO 尝试建立 TCP 或 socket 连接时被操作系统或 MySQL 服务直接拒绝——问题一定出在连接链路的某一层,而不是框架本身。
看清楚 PDOException::getMessage() 里的真实线索
ThinkPHP 只透传 PDO 异常,PDOException::getMessage() 才是唯一可信的诊断入口。别扫一眼“连接失败”就改配置,先复制整行 message:
- “
SQLSTATE[HY000] [2002] Connection refused” → 服务没起来、端口没监听、防火墙拦了、或 hostname 解析错位 - “
SQLSTATE[HY000] [2002] No such file or directory” →hostname写了localhost,但 MySQL 没启用 Unix socket,或php.ini里pdo_mysql.default_socket路径和 MySQL 实际 socket 文件不一致(Mac M1 上常见路径是/opt/homebrew/var/mysql/mysql.sock) - “
SQLSTATE[HY000] [1045] Access denied for user” → 用户权限不匹配,比如数据库里只建了'root'@'localhost',但 PHP 配的是127.0.0.1,这两者在 MySQL 权限系统里是不同账号
Linux/macOS 下 localhost 和 127.0.0.1 的行为差异必须分清
这俩看起来一样,但在 MySQL 连接层完全走不同通道:
-
localhost→ PDO 默认走 Unix socket(绕过 TCP),要求 MySQL 配置了socket且路径对得上 -
127.0.0.1→ 强制走 TCP 协议,依赖 MySQL 是否监听该地址 + 端口(默认 3306) - ThinkPHP 配置中若写
hostname => 'localhost'却没开 socket,或写'127.0.0.1'但 MySQLbind-address = 127.0.0.1被注释/未生效,都会触发[2002] Connection refused - 验证方式:终端执行
mysql -h 127.0.0.1 -P 3306 -u root -p(必须用 IP,不能用 localhost);如果能连上,说明 TCP 正常,问题大概率出在 socket 路径或 hostname 语义错位
Docker 和云环境的 hostname 绝对不能硬写 127.0.0.1
容器内 127.0.0.1 指向容器自己,不是宿主机;云服务器上它也不代表数据库实例所在机器:
- Docker Compose 场景:数据库服务名是
mysql,PHP 容器里hostname必须配成mysql,不是127.0.0.1或localhost - 阿里云 RDS / 腾讯云 CDB:hostname 填控制台给的外网或内网域名(如
xxx.mysql.rds.aliyuncs.com),并确认安全组放行 3306 入方向 - Docker 容器访问宿主机 MySQL:用
host.docker.internal(Docker Desktop)或宿主机实际内网 IP(Linux Docker),不能写127.0.0.1 - MySQL 配置需同步调整:容器内
mysqld.cnf中bind-address设为0.0.0.0,并执行UPDATE user SET host='%' WHERE user='root'; FLUSH PRIVILEGES;
端口和防火墙是沉默的杀手
很多情况下服务明明 running,但连不上,就是卡在这一层:
- Linux 查监听:
sudo netstat -tulnp | grep :3306,确认输出里有mysqld进程绑定到*:3306或127.0.0.1:3306;若只有127.0.0.1:3306,远程连不上 - Ubuntu 防火墙:
sudo ufw status,若显示 inactive 可忽略;active 则运行sudo ufw allow 3306 - Windows 防火墙:进“高级安全 Windows Defender 防火墙”→“入站规则”,新建规则放行 TCP 端口 3306
- 云服务器:安全组必须显式添加 3306 入方向规则,源 IP 可设为
0.0.0.0/0(测试用)或具体应用服务器 IP(生产用) - ThinkPHP 的
hostport必须是整数类型,写成'3306'(字符串)在 TP5.1+ 会静默 fallback,某些环境直接失败
真正麻烦的点往往不在“服务启没启”,而在于 hostname 语义、socket 路径、容器网络、认证插件(MySQL 8.0+ 默认 caching_sha2_password,老版 PHP 可能不兼容)这几处隐性错位。每次改完配置,务必用命令行 mysql -h ... 直连验证,别依赖框架日志做唯一判断。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











