Connection refused 表明 MySQL 服务未启动或未监听 TCP 端口;应先检查 mysqld 进程和 3306 端口占用,再确认 my.cnf 中 port、bind-address 配置及 skip-networking 状态,并区分 DB_HOST=localhost(走 socket)与 127.0.0.1(走 TCP)。

phpEnv 里 MySQL 没监听 3306,Connection refused 是表象
不是 phpEnv 配置错了,而是它内置的 MySQL 服务压根没启动,或启动了但没监听 TCP 端口。你看到的 Connection refused(错误号 111)意味着 PHP 尝试 connect() 时,操作系统直接返回“没人应答”,连认证环节都没走到。
先别改 .env 或 config/database.php——90% 的 case 是服务根本没跑起来。
- 打开终端,执行
ps aux | grep mysqld,确认有没有mysqld进程在运行;没有就说明服务没启 - 有进程?再查端口:
lsof -i :3306或netstat -tuln | grep :3306,若无输出,说明 MySQL 虽然跑了,但只监听 socket(/tmp/mysql.sock),没开 TCP - phpEnv 默认可能用 socket 连接,但 Laravel/PDO 默认走 TCP;你配
DB_HOST=localhost,PHP 会尝试走 socket,而 MySQL 若被设为skip-networking或bind-address=127.0.0.1却没开 port,就会断连
phpEnv 的 my.cnf 常见监听配置陷阱
phpEnv 自带的 MySQL 配置文件(通常在 ~/.phpenv/versions/*/etc/my.cnf 或 ~/.phpenv/plugins/php-build/share/php-build/default_configure_options 生成路径下)容易漏掉关键项。
重点检查 [mysqld] 段里这三项:
立即学习“PHP免费学习笔记(深入)”;
-
port = 3306—— 必须显式写,不能依赖默认 -
bind-address = 127.0.0.1—— 不要写成localhost(MySQL 会把它当 socket 名处理);也不要用0.0.0.0(除非你真需要外网访问,且已配防火墙) - 确认没有
skip-networking这行;有就删掉或注释
改完必须重启 MySQL:phpenv mysql-restart(如果 phpEnv 提供该命令),否则 my.cnf 修改不生效。
DB_HOST=localhost 和 DB_HOST=127.0.0.1 在 phpEnv 下行为完全不同
这是最容易踩的坑:在 phpEnv 环境中,localhost 会让 PHP 的 mysqli/pdo_mysql 强制走 Unix socket,而 127.0.0.1 才走 TCP —— 但你的 MySQL 可能只开了其中一种。
验证方法很简单:
- 用
mysql -h 127.0.0.1 -u root -p测试:能进 → 说明 TCP 监听 OK,此时 Laravel 的DB_HOST必须填127.0.0.1 - 用
mysql -h localhost -u root -p测试:能进但上一条失败 → 说明只开了 socket,Laravel 就得配unix_socket=/tmp/mysql.sock(并删掉port和host冲突项) - 两条都失败?回到前两节,检查进程和
my.cnf
注意:DB_PORT 在用 localhost 时会被忽略;只有 127.0.0.1 或 IP 地址时才生效。
Docker + phpEnv 混用时 DB_HOST 别填 localhost
如果你在 Docker 容器里跑 PHP(比如用 phpEnv 构建的镜像),又想连宿主机的 MySQL,DB_HOST=localhost 是错的——它会指向容器自己,而不是宿主机。
正确做法取决于你的网络模式:
- Docker for Mac/Windows:
DB_HOST=host.docker.internal - Linux Docker:
DB_HOST=172.17.0.1(通常是 docker0 网桥地址,用ip route | awk '/default/ {print $3}'确认) - 自定义 bridge 网络:
DB_HOST=宿主机真实 IP(如192.168.1.100),且宿主机 MySQL 必须监听该 IP(bind-address = 0.0.0.0或对应 IP),并放行防火墙
顺带一提:Docker 容器内执行 ping localhost 成功 ≠ MySQL 可连,因为 ping 走的是 loopback,而 MySQL 连接走的是 TCP socket 层,受 my.cnf 和防火墙双重约束。



















