要让ThinkPHP断线重连生效,必须同时配置'break_reconnect'=>true、'type'=>'pdo_mysql'、'params'=>[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION],缺一不可;事务内失效,CLI/Swoole需主动探活。

要让 ThinkPHP 的数据库配置真正支持断线重连,光写 break_reconnect => true 是不够的——它必须和几个关键参数协同生效,缺一不可。否则连接断开后依然报 “MySQL server has gone away”,框架根本不会尝试重建。
必须显式启用 PDO 异常模式
ThinkPHP 的断线重连只在 PDO 抛出异常时触发,而 PDO 默认是静默处理错误的。如果没设异常模式,错误直接被吞掉,break_reconnect 就像没写一样。
- 在数据库配置的
params数组里,一定要加上:PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION - 注意:
.env文件无法覆盖嵌套数组(比如params),所以这行必须写在config/database.php里 - 检查你的驱动类型是否为
'type' => 'pdo_mysql';mysqli或mysql驱动完全不识别该机制
配置项必须放在连接层级,不能靠继承
break_reconnect 是单个数据库连接的开关,不是全局设置。它只对当前连接实例生效,不会影响其他连接或已断开的旧连接。
- 确保它写在具体连接配置内部,例如
'connections' => ['mysql' => [...]]的mysql数组里 - 不要依赖中间件、事件或运行时修改来“补救”——配置要在初始化阶段就到位
- 可选增强匹配精度:
'break_match_str' => ['2006', 'MySQL server has gone away'],避免误判其他错误
事务中自动重连完全失效,需手动兜底
这是最容易引发数据错乱的盲区:只要执行过 Db::startTrans() 或 Db::transaction(),连接一旦中断,框架会直接抛异常,break_reconnect 不介入、不重试、不恢复事务上下文。
立即学习“PHP免费学习笔记(深入)”;
- 事务内失败后,原事务已销毁,后续调用
commit()或rollback()会报 “There is no active transaction” - 关键操作(如支付、库存扣减)必须自己封装重试逻辑:每次失败都
close()+startTrans(),不能复用旧事务引用 - 建议最多重试 2~3 次,每次间隔
usleep(100000),避免瞬时雪崩
CLI 和 Swoole 环境需单独处理
Web 请求(FPM)是短连接,重连影响小;但队列、定时任务、Swoole Worker 是长驻进程,连接可能空闲数小时,被 MySQL 的 wait_timeout 主动踢掉。此时仅靠配置不够,得主动干预。
- CLI 场景推荐动态覆盖:在命令类
execute()开头调用Db::init(array_merge($config, ['break_reconnect' => true])) - Swoole 下需周期性探活:在
onWorkerStart初始化连接,并用Timer::tick(300000, [...])每 5 分钟执行SELECT 1检测存活 - 禁用
PDO::ATTR_PERSISTENT => true—— 它不解决断线问题,反而掩盖连接泄漏,还可能污染会话状态



















