PHP7.0+Laravel5.*报Packets out of order错误求优化解决方案
解决Laravel5.* + PHP7.0 数据库数据包乱序问题的优化方案
遇到Packets out of order. Expected 1 received 0. Packet size=145这个问题,不用每个文件都加\DB::reconnect(),试试下面几个全局处理方案:
1. 全局HTTP中间件自动检测重连
写一个全局中间件,为所有HTTP请求自动处理连接异常:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\DB; class ReconnectDatabase { public function handle($request, Closure $next) { try { // 执行简单查询检测连接状态 DB::select('SELECT 1'); } catch (\Exception $e) { // 仅针对数据包乱序异常触发重连 if (str_contains($e->getMessage(), 'Packets out of order')) { DB::reconnect(); } // 其他异常正常抛出 throw $e; } return $next($request); } }
写完后在app/Http/Kernel.php的$middleware数组中注册这个中间件,所有HTTP请求都会自动走连接检测流程。
2. 命令/队列任务全局处理
如果问题多出现于Artisan命令或队列任务中:
- 自定义命令基础类:写一个基础命令类,所有任务命令继承它,启动时自动检测连接:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; class BaseCommand extends Command { public function __construct() { parent::__construct(); $this->checkDbConnection(); } protected function checkDbConnection() { try { DB::select('SELECT 1'); } catch (\Exception $e) { if (str_contains($e->getMessage(), 'Packets out of order')) { DB::reconnect(); } throw $e; } } }
后续自定义命令时,继承BaseCommand即可,无需重复编写重连逻辑。
- 队列任务监听:在
app/Providers/AppServiceProvider.php的boot方法中添加事件监听,每个队列任务启动前自动检测连接:
use Illuminate\Queue\Events\JobProcessing; public function boot() { $this->app['events']->listen(JobProcessing::class, function (JobProcessing $event) { try { \DB::select('SELECT 1'); } catch (\Exception $e) { if (str_contains($e->getMessage(), 'Packets out of order')) { \DB::reconnect(); } } }); }
3. 调整数据库配置参数
在config/database.php的mysql配置中添加或优化以下参数,提升连接稳定性:
'mysql' => [ // 原有配置... 'options' => [ PDO::ATTR_TIMEOUT => 30, // 设置连接超时时间 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4', PDO::MYSQL_ATTR_RECONNECT => true, // 开启自动重连(PHP7.0需对应驱动版本支持) ], ],
注意:PDO::MYSQL_ATTR_RECONNECT的有效性依赖mysql驱动版本,建议先测试验证。
4. 更新数据库驱动
检查并升级mysqlnd或mysqli驱动到适配PHP7.0的最新稳定版,旧驱动的连接管理bug可能是问题的核心原因。
内容的提问来源于stack exchange,提问作者Sourabh Singla
相关产品推荐
相关产品推荐

