Doctrine\DBAL\DBALException“使用参数执行'...'时发生异常[...]警告:发送QUERY数据包时出错。PID =

Doctrine\DBAL\DBALException "An exception occurred while executing '...' with params [...] Warning: Error while sending QUERY packet. PID=

上下文:一个 Symfony 4.4 网络应用托管在基于 Ubuntu 的 Docker 图像上,连接到 MySQL 5.7 Azure 数据库 MySQL。

我们有许多错误(每 14 天在 Sentry 中发生 >5K 事件),例如:


案例一

Doctrine\DBAL\DBALException

An exception occurred while executing 'SELECT qd.id as uuid, qd.content as content FROM queue_data qd WHERE qd.tag = ? LIMIT 1000' with params [...]:

Warning: Error while sending QUERY packet. PID=...

来自:

    // App\Utility\Queue\Service\QueueDataService::getData
    
    public function getData(string $tag, int $limit = self::DEFAULT_LIMIT): array
    {
        return $this->getQueryBuilderForTag($tag)
            ->select('qd.id as uuid', 'qd.content as content')
            ->setMaxResults($limit)
            ->execute()
            ->fetchAll(FetchMode::ASSOCIATIVE);
    }

案例二

Doctrine\DBAL\DBALException

An exception occurred while executing 'SET NAMES utf8mb4':

Warning: Error while sending QUERY packet. PID=...

来自:

// custom code

private function myMethod(){
    ...
    $this->connection->executeQuery('SET NAMES utf8mb4');
    ...
}

...


Sentry 显示此消息的 245 个“问题”(超过 14 天)=> 这是同一问题的 245 个不同案例,每个实例都有 1 到 2K 个事件(有些实例实际上来自执行非常频繁的消费者).

不过,好像对用户没有什么影响...

还有其他人遇到同样的问题吗? 有可能解决这个问题吗? 怎么样?

干杯!

发现问题:

  • 在我的数据库服务器 (MySQL) 上,我将参数 wait_timeout 设置为 120 秒
  • 我有几个由 Supervisor 管理的消息消费者进程
  • 这些工作人员每个进程消耗几条消息,并且没有 time-limit ,因此他们可能会等待一条新消息消耗超过 2 分钟
  • 在那种情况下,数据库服务器关闭了数据库连接,但 Doctrine 客户端直到它尝试执行一个会失败的请求时才意识到这一点

我的修复是:

  • 将数据库服务器配置 wait_timeout 增加到 600 秒(10 分钟)
  • 向我的消费者进程添加 time-limit 300 秒(5 分钟)

根本原因仍应由 Doctrine 团队解决:在尝试执行查询之前,它没有 ping 服务器(测试连接是否仍然打开),这看起来很奇怪。

干杯!