php消费rabbitmq时易触发mysql 2006错误,因thinkphp-queue等cli消费者长驻运行并复用连接,而mysql默认wait_timeout=28800秒,低频场景下空闲期超时致连接被服务端主动断开;须同步修改my.ini中wait_timeout、interactive_timeout为300并重启mysql服务,禁用pdo持久化,优先采用queue:listen模式实现连接隔离。

为什么PHP消费RabbitMQ时容易触发MySQL 2006错误
因为ThinkPHP-Queue或自研CLI消费者会长驻运行,复用同一个MySQL连接;而MySQL服务端默认wait_timeout=28800(8小时),看似够用,但实际中——一次任务处理完到下一次拉取之间可能空闲几十秒甚至几分钟,尤其在低频队列场景下,这个空闲期很容易超过服务端设定值。连接被MySQL主动断开后,PHP进程仍拿着失效句柄继续执行$pdo->query(),立刻报SQLSTATE[HY000] [2006] MySQL server has gone away。
必须改MySQL配置,不能只靠PHP重连
光在代码里捕获异常再重建连接是补救,不是根治。频繁重连会放大问题:比如事务中途断开、prepared statement失效、临时表丢失。真正要做的,是让连接在业务生命周期内不被杀掉。
- 找到phpEnv安装目录下的
mysql\my.ini(不是php.ini) - 在
[mysqld]段下添加或修改三行:wait_timeout = 300 interactive_timeout = 300 max_allowed_packet = 32M
- 保存后,**必须通过phpEnv托盘图标重启MySQL服务**(仅重启Apache/Nginx无效)
- 进phpMyAdmin执行
SHOW VARIABLES LIKE 'wait_timeout';确认返回值是300
PDO连接必须禁用持久化并显式释放
PHP CLI进程不会自动回收PDO连接资源,PDO::ATTR_PERSISTENT => true在phpEnv里等于埋雷:子进程结束时连接没真关,残留连接堆积+空闲超时=2006高发。
- 创建PDO时强制关闭持久化:
$pdo = new PDO($dsn, $user, $pass, [ PDO::ATTR_PERSISTENT => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); - 脚本末尾加
$pdo = null;,尤其在长循环或while(true)消费逻辑里 - 避免在
foreach ($tasks as $task) { new PDO(...) }这种写法——每次new都开新连接,很快耗尽max_connections
ThinkPHP-Queue推荐用listen模式而非work
php think queue:work是单进程长驻,连接复用不可避免;php think queue:listen则是每来一个任务起一个新PHP进程,天然隔离连接生命周期——每个任务都走“连接→操作→关闭”完整流程,彻底规避空闲断连。
- 只需改启动命令,无需动数据库配置或业务代码
- 配合
supervisor管理时,把command=php /path/to/think queue:listen写进配置即可 - 唯一代价是进程创建开销,但对非高频任务(如每5秒以上触发一次)几乎无感
最常被忽略的一点:改完my.ini后不重启MySQL服务,或者改了wait_timeout却没同步改interactive_timeout(MySQL文档明确要求两者必须一致才对新连接生效)。这两个动作漏掉任何一个,配置就等于白改。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











