PHP连接MySQL超时本质是客户端未适配服务端wait_timeout设置,需协同调整客户端连接超时参数(如MYSQLI_OPT_CONNECT_TIMEOUT)、服务端wait_timeout/interactive_timeout,并在应用层捕获2006错误实现重连。

phpEnv 中 PHP 连接 MySQL 超时,本质是 MySQL 客户端连接行为未适配服务端 wait_timeout 设置,不是 phpEnv 本身有独立超时开关。
php.ini 中的 mysql.default_socket 和 mysqli.default_socket 不影响超时
这两个配置只指定本地 socket 路径,和连接建立后的空闲等待无关。误调它们不会解决超时问题,反而可能导致连接失败(比如路径不存在时直接报 Connection refused)。
- 检查实际 MySQL 服务监听方式:
netstat -tlnp | grep :3306,确认是127.0.0.1:3306(TCP)还是/tmp/mysql.sock(socket) - 若用 TCP 连接(如
host=localhost),default_socket配置会被忽略 - 真正影响连接阶段的是
default_socket_timeout(单位秒),但仅控制 connect() 系统调用超时,非 query 超时
mysqli::options() 必须在 new mysqli() 后、connect() 前调用
很多用户把 MYSQLI_OPT_CONNECT_TIMEOUT 或 MYSQLI_OPT_READ_TIMEOUT 放在 mysqli_connect() 之后,结果完全不生效 —— 因为连接已建立,选项失去作用。
- 正确顺序示例:
$mysqli = new mysqli();
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
$mysqli->options(MYSQLI_OPT_READ_TIMEOUT, 30);
$mysqli->options(MYSQLI_OPT_WRITE_TIMEOUT, 30);
$mysqli->real_connect('127.0.0.1', 'user', 'pass', 'db', 3306);
-
MYSQLI_OPT_CONNECT_TIMEOUT:仅控制 TCP 握手耗时上限(建议设 3–5 秒) -
MYSQLI_OPT_READ_TIMEOUT:控制从服务器读取响应的单次阻塞上限(应对慢查询或网络抖动) - 注意:PHP 7.4+ 才支持
MYSQLI_OPT_READ_TIMEOUT在real_connect()前设置;旧版本需用mysqli_options($link, ...)配合过程式写法
MySQL 服务端 wait_timeout 和 interactive_timeout 是根源
phpEnv 自带的 MySQL(如 MariaDB 10.6+)默认 wait_timeout=28800(8 小时),但若你改过配置或用了 Docker 镜像,可能被设成 60 秒 —— 这会导致空闲连接在 60 秒后被服务端主动断开,PHP 再次 query 时抛出 MySQL server has gone away。
立即学习“PHP免费学习笔记(深入)”;
- 查当前值:
mysql -u root -e "SHOW VARIABLES LIKE '%timeout%';" - 临时修改(重启失效):
SET GLOBAL wait_timeout = 28800; - 永久修改:编辑 phpEnv 对应 MySQL 的
my.cnf(通常在phpenv/mysql/conf/my.cnf),在[mysqld]下加:
wait_timeout = 28800 interactive_timeout = 28800
- 改完必须重启 MySQL:
phpenv service mysql restart,否则不生效 - 注意:如果 PHP 使用了长连接(
PDO::ATTR_PERSISTENT => true或mysqli::real_connect()传MYSQLI_CLIENT_FOUND_ROWS外的 flag),更依赖wait_timeout;短连接则几乎不受影响
最常被忽略的是:超时问题往往出现在「连接复用」场景下 —— 比如 CLI 脚本里循环执行多个查询,中间间隔超过服务端 wait_timeout,但代码没做重连逻辑。这时候调高 PHP 端 timeout 参数毫无意义,必须两端协同调整,且应用层要捕获 mysqli_connect_errno() === 2006 并重建连接。



















