默认不开启断线重连,需手动配置break_reconnect => true才生效;否则MySQL空闲超时断开后,后续查询直接抛异常。

默认不开启断线重连,必须手动配 break_reconnect 才生效。 否则一旦 MySQL 主动断开(比如空闲超时、网络抖动),后续查询直接抛异常,不是自动重试。
为什么 work 模式下容易断线
ThinkPHP 队列的 work 模式是常驻进程,启动时建一次连接,之后复用。但 MySQL 默认 wait_timeout=28800(8 小时),低峰期无操作就会被服务端主动踢掉。进程 unaware,下次查库就报 MySQL server has gone away。
常见表现:
- 凌晨或周末后首次请求失败
- 日志里反复出现 PDOException 或 “Connection lost”
- 错误只在队列任务里出现,Web 请求正常(因为 Web 是短连接)
break_reconnect 必须显式设为 true
这个开关在 config/database.php 的数据库配置里,不是全局开关,也不是中间件行为。不写就是 false,写了才管用。
立即学习“PHP免费学习笔记(深入)”;
正确配置示例:
'break_reconnect' => true,
'params' => [
\PDO::ATTR_TIMEOUT => 5,
\PDO::ATTR_EMULATE_PREPARES => false,
],
注意点:
-
break_reconnect只对当前连接实例生效,不作用于已断开的旧连接 - 它只在“执行 SQL 报错时”触发重连,不是定时保活;所以第一次失败仍会暴露给上层(需配合 try/catch)
- 重连成功后,会重新执行原 SQL —— 这意味着事务上下文丢失,不能用于需要强一致性的场景
持久连接(persistent)和断线重连不是一回事
persistent => true 是让 PHP 进程复用底层 socket,避免频繁握手开销;但它不解决空闲断连问题,反而更容易撞上 wait_timeout。两者要分开看:
- 高并发短请求(如 Web 接口):可开
persistent,但必须配break_reconnect - 长周期任务(如队列、定时脚本):建议关
persistent,靠break_reconnect+ 合理的timeout参数兜底 - 两者都开,可能掩盖连接泄漏问题,增加排查难度
真正稳的组合:断线重连 + 连接池 + 被动检测
单靠 break_reconnect 只是“出错了再救”,生产环境建议叠加:
- 用
PdoPool类库管理连接池,连接用完归还时做健康检查(比如发个PING) - 队列任务开头加
Db::connect()->query('SELECT 1')主动探活(轻量,比等报错更早发现问题) - 监控
show status like 'Threads_connected',防止连接数无声增长到上限
最易忽略的一点:break_reconnect 不会重连事务中的连接。如果在事务里断线,重连后原事务已失效,继续执行会出错 —— 这类逻辑必须自己控制回滚与重试边界。



















