错误代码2006表示mysql连接已断开,主因是wait_timeout超时,而非配置错误或无法连接;需通过errorinfo[1]确认为2006,再结合调整超时参数或代码层重连解决。

直接看 PDOException 的 errorInfo[1] 是不是 2006
报错里带 General error: 2006 MySQL server has gone away,说明连接已断开,不是配置写错了,也不是连不上去,而是“连上了,但后来断了”。关键证据在 $e->errorInfo[1] —— 它必须是 2006(或偶尔是 2013),才确认是超时断连。别被日志里“Connection refused”“Access denied”等相似错误干扰,先定位数字码。
MySQL 的 wait_timeout 太小,CLI 场景最常触发
MySQL 默认 wait_timeout 是 28800 秒(8 小时),但 ThinkPHP 8 的 CLI 命令(如定时任务、队列消费)若长时间空闲,很容易踩中这个阈值。此时连接还在 PHP 进程里挂着,但 MySQL 已单方面关闭它。
- 改 MySQL 配置:在
my.cnf或my.ini中加这两行,然后重启 MySQL
wait_timeout = 31536000 interactive_timeout = 31536000
- 临时生效(不用重启):在 ThinkPHP 启动连接后立刻执行 SQL
$this->execute("SET SESSION wait_timeout = 31536000, interactive_timeout = 31536000");
- 注意:不要只改
max_allowed_packet——那是解决大数据包截断的,和 2006 无关
ThinkPHP 8 没内置自动重连,得自己补逻辑
TP8 的 PDOConnection 类默认不处理 2006 断连,异常直接往上抛。你得在执行 SQL 前加一层兜底:
- 在自定义数据库驱动或基类模型里,重写
query()和execute()方法 - 捕获
PDOException,检查$e->errorInfo[1] === 2006 - 手动清空当前连接句柄:
$this->linkID = [];,再调用$this->initConnect(false)重建
别依赖“连接池”或“长连接保活心跳”——TP8 原生不支持这些,硬加容易和框架生命周期冲突。
容易被忽略的两个点:PDO 属性和 CLI 环境差异
即使改了 MySQL 超时时间,2006 还可能反复出现,问题往往出在这两处:
-
PDO::ATTR_PERSISTENT设为true会加剧问题:持久连接在 CLI 下无法复用,反而更容易僵死 - CLI 模式下,
APP_DEBUG关闭时,部分异常堆栈会被吞掉,导致你以为没报错,其实是静默失败 - 某些云数据库(如阿里云 RDS)会强制更短的
wait_timeout(比如 300 秒),且不允许修改,这时只能靠代码层重连
真正在生产环境跑 CLI 任务,别只盯着 MySQL 配置——重连逻辑 + 明确的超时容忍策略,才是稳住的关键。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











