“Lost connection to MySQL server during query”本质是MySQL服务端因wait_timeout超时主动断开空闲连接,而Hyperf连接池未剔除失效连接导致复用“僵尸连接”;需启用heartbeat心跳('heartbeat' => true)、设置max_idle_time略小于wait_timeout,并对齐read/write_timeout与PDO超时参数。

Hyperf 中 MySQL 报错 2013: Lost connection to MySQL server during query,本质不是网络断开,而是连接被服务端主动关闭后,客户端仍尝试复用该连接——根源在连接池未及时剔除失效连接,导致“MySQL server has gone away”。
根本原因:连接池复用了已被 MySQL kill 的连接
MySQL 服务端配置了 wait_timeout(默认 8 小时),空闲连接超时后会被强制断开。但 Hyperf 连接池默认不检测连接有效性,下次从池中取出这个“僵尸连接”执行 SQL 时,就触发 2013 错误。
- 错误常出现在低频接口、定时任务首次执行、或服务刚启动后长时间无请求的场景
- 不是每次查询都报错,而是“偶发+集中爆发”,尤其在 Redis + MySQL 混合调用中更易连锁触发
- 日志里可能同时出现
MySQL server has gone away和后续 RedisConnection reset by peer,说明协程上下文已被污染
必须开启 heartbeat 心跳机制
这是最直接有效的解法。配置需同时满足两个硬性条件:
-
'heartbeat' => true:显式启用心跳检测(默认为false) -
'max_idle_time' => 86000(单位毫秒):必须比 MySQL 的wait_timeout少至少 30–60 秒,例如 MySQL 设为 86400 秒(24 小时),这里设 86000(23h53m)
配置位置:config/autoload/databases.php 中对应数据库的 pool 配置块内,不是全局设置。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
同步检查 MySQL 服务端与客户端超时对齐
仅配 heartbeat 不够,还需确保三层超时不冲突:
-
服务端:确认
show variables like 'wait_timeout';,建议设为 86400 或更低(如 3600) -
客户端 I/O:在数据库
options中补全'read_timeout' => 5.0和'write_timeout' => 5.0(Swoole 驱动必需) -
PDO 层:添加
\PDO::ATTR_TIMEOUT => 3,防止 prepare/execute 卡死
三者关系应为:max_idle_time ,否则心跳无效或掩盖真实问题。
避免事务污染协程上下文
如果 2013 出现在 DB 事务之后(比如 DB::transaction() 内部抛异常未提交),可能引发连锁反应:MySQL 断连 → 事务回滚失败 → Redis 客户端在损坏的协程上下文中继续调用 → 直接 hang 住或报 Connection reset。
- 所有数据库操作务必包裹
try/catch,确保事务无论成功失败都显式commit()或rollback() - 禁用长事务:UPDATE/SELECT FOR UPDATE 类操作必须带索引,避免锁表升级;事务内不要混入 Redis、HTTP 等外部调用
- 临时验证:在出错前加
var_dump($pdo->getAttribute(\PDO::ATTR_CONNECTION_STATUS));,若返回 false 可确认连接已失效

















