核心原因是MySQL的wait_timeout参数在CLI进程空闲时主动断开连接,而ThinkPHP未及时重连;需配置'break_reconnect'=>true、'params'=>[PDO::ATTR_TIMEOUT=>5],并合理设置wait_timeout=300秒。

ThinkPHP6 定时任务数据库连接超时,核心原因是 CLI 进程长期驻留、复用旧连接,而 MySQL 服务端在空闲期主动断开(wait_timeout 触发),但 TP 并未及时感知或重建——不是网络问题,也不是 PHP 脚本卡死,而是连接生命周期与业务周期不匹配。
确认是否真是 wait_timeout 导致
先快速定位根源,避免盲目调参:
- 查错误日志:出现
SQLSTATE[HY000] [2006] MySQL server has gone away,且发生在定时任务启动后几分钟(非首次执行)→ 高概率是wait_timeout断连 - 进 MySQL 执行:
SHOW VARIABLES LIKE 'wait_timeout';,若值为 60 或 300(云数据库常见),而你的定时任务单次执行间隔 > 该值 → 必须调整 - 运行
SHOW PROCESSLIST;,观察连接状态:大量Sleep行,Time 列数值稳定接近某个整数(如 298、597)→ 直接对应当前wait_timeout值
ThinkPHP 配置层必须加的两项
仅改 MySQL 参数不够,TP 层需主动配合断线重连逻辑:
-
开启自动重连:在
config/database.php的对应连接配置中,加上'break_reconnect' => true -
设置 PDO 连接建立超时:在相同配置里加入
'params' => [\PDO::ATTR_TIMEOUT => 5],防止建连阶段卡死(尤其网络不稳定时) - 注意:如果用了多数据库连接(如
Db::connect('log')),每个连接配置都得单独补上这两项,不能只配default
MySQL 服务端参数要对齐业务节奏
别直接拉到 8 小时,按实际需要设更安全:
- 查当前值:
SHOW VARIABLES LIKE '%timeout%'; - 若定时任务最长单次执行耗时 ≤ 45 秒,建议设
wait_timeout = 300(5 分钟),兼顾稳定性与资源释放 - 执行生效命令(仅影响新连接):
SET GLOBAL wait_timeout = 300;;已有连接仍按旧值计时,可重启 MySQL 或等其自然失效 -
interactive_timeout建议同步设为相同值,避免你在命令行调试时也意外断连
CLI 场景下额外加固措施
定时任务常以 php think timer:run 等方式常驻运行,需防连接堆积和状态残留:
- 任务入口处手动保活:在定时任务主逻辑开头加
Db::getPdo()->ping() || Db::close();,失败则强制重连 - 避免循环中反复
new Db()或未释放连接,每次任务结束确保无长持连接句柄 - 检查 PHP CLI 的
default_socket_timeout(php --ini查 php.ini 路径),设为60或更高,避免底层 socket 层提前中断
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











