为了账号安全,请及时绑定邮箱和手机立即绑定

PDOException:数据包乱序。预期收到 0 1。数据包大小=23

PDOException:数据包乱序。预期收到 0 1。数据包大小=23

PHP
慕丝7291255 2023-09-15 21:49:30
我有一个 Laravel Spark 项目,它使用 Horizon 来管理 Redis 的作业队列。在本地(在我的 Homestead 盒子、Mac OS 上)一切都按预期工作,但在我们新的 Digital Ocean(Forge 配置)Droplet(内存优化的 256GB、32vCPU、10TB 和 1x 800GB VPS)上,我不断收到错误:PDOException: Packets out of order. Expected 0 received 1. Packet size=23或者该错误的某些变体,其中数据包大小信息可能不同。经过数小时/数天的调试和研究,我在 StackOverflow 和其他地方看到了许多帖子,这些帖子似乎表明可以通过执行以下列出的许多操作来解决此问题:在我的 database.php 配置中设置PDO::ATTR_EMULATE_PREPARES为 true。这对问题绝对没有影响,实际上引入了另一个问题,即整数被转换为字符串。设置DB_HOST为127.0.0.1而不是localhost,以便它使用 TCP 而不是 UNIX 套接字。同样,这没有任何效果。DB_SOCKET通过登录 MySQL (MariaDB) 并运行将套接字路径列出为 来设置为 MySQL 中show variables like '%socket%';列出的套接字路径/run/mysqld/mysqld.sock。我也离开DB_HOST设置为localhost。这也没有效果。我确实注意到的一件事是,变量pdo_mysql.default_socket设置为/var/run/mysqld/mysqld.sock,我不确定这是否是问题的一部分?我已将 MySQL 配置设置大幅增加到/etc/mysql/mariadb.conf.d/50-server.cnf以下内容:key_buffer_size = 2048Mmax_allowed_packet = 2048Mmax_connections = 1000thread_concurrency = 100query_cache_size = 256M我必须承认,改变这些设置是最后的手段/抓住稻草类型的场景。然而,这确实在一定程度上缓解了这个问题,但并没有完全解决它,因为 MySQL 在 99% 的情况下仍然会失败,尽管是在后期。就队列而言,我总共分为1,136 workers6 个主管/队列,并且全部通过 Laravel Horizon 处理,它作为守护进程运行。我还使用 Laravel Websockets PHP 包进行广播,同样,它也作为守护进程运行。我当前的环境配置如下(敏感信息省略)。服务器设置如下:最大文件上传大小:1024最大执行时间:300PHP 版本:7.4MariaDB 版本:10.3.22我检查了 MySQL 服务器崩溃/消失时的所有日志(见下文),MySQL 日志中根本没有任何内容。没有任何错误。我也没有看到任何内容:/var/log/nginx/error.log/var/log/nginx/access.log/var/log/php7.4-fpm.log我目前仍在挖掘和调试,但现在,我被难住了。这是我第一次遇到这个错误。这可能是因为访问数据库(读/写)太快吗?有关队列如何工作的一些信息。我有一个初始控制器,它将作业分派到队列。一旦该作业完成,它就会触发一个事件,然后启动按顺序运行其他几个侦听器/事件的过程,所有这些都取决于在触发新事件和新侦听器/作业占用工作之前完成的先前作业。总共播出了 30 个事件。总共有 30 名听众。总共有5个职位。这些都根据运行的侦听器/作业及其触发的事件按顺序工作。我还监控了laravel.log现场情况,当崩溃发生时,根本没有记录任何内容。虽然,我偶尔会得到production.ERROR: Failed to connect to Pusher.MySQL是否崩溃的信息,所以我认为这与这个问题没有任何关系。我什至注意到 Laravel API 速率限制已达到,因此我确保将其从 60 大幅增加到 500。仍然没有高兴。最后,运行哪个事件、作业或监听器似乎并不重要,因为错误是随机发生的。因此,不确定它是特定于代码的,但很可能是。希望我已经提供了足够的背景和详细信息来获得一些帮助,但如果我错过了任何内容,请告诉我,我会将其添加到问题中。谢谢。
查看完整描述

4 回答

?
慕神8447489

TA贡献1780条经验 获得超1个赞

对我来说,解决这个问题的是增加最大数据包大小。

在 中my.cnf,我添加了:

max_allowed_packet=200M

然后service mysql stop,,,service mysql start它成功了:)


查看完整回答
反对 回复 2023-09-15
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

我们收到了类似的关于数据包乱序的 PHP 警告。为我们解决这个问题的是增加MySQL my.cnf 中的max_connections 。您当前的 max_connections 可能是 1024。我们将其增加到 4096,警告消失了。在 MySQL 中,您可以使用以下命令查看当前的 max_connections:

SHOW VARIABLES LIKE "%max_connections%";
or
mysqladmin variables | grep max_connections


查看完整回答
反对 回复 2023-09-15
?
杨__羊羊

TA贡献1943条经验 获得超7个赞

我遇到了一个可重现的类似问题,这是一个编程错误:
我使用的是无缓冲的数据库游标,并且在触发其他数据库操作之前没有关闭游标。抛出的确切错误是Packets out of order. Expected 1 received 2.

查看完整回答
反对 回复 2023-09-15
?
慕标5832272

TA贡献1966条经验 获得超4个赞

首先要检查的是wait_timeoutMySQL 服务器的时间,与应用程序在查询之间花费的时间有关。通过在 SQL 查询之间休眠时间超过wait_timeout秒,我能够一致地重新创建此错误。

如果您的应用程序执行查询,然后在一段时间内执行其他操作,并且花费的时间超过该时间,则 MySQL 服务器将终止连接,但您的 PHP 代码可能不知道服务器已断开连接。如果 PHP 应用程序随后尝试使用关闭的连接发出另一个查询,它将生成此错误(在我的测试中,与Expected 0 received 1.

您可以通过以下方式解决此问题:

  • wait_timeout在服务器上全局扩展或使用命令在每个会话的基础上扩展SET session wait_timeout=<new_value>;

  • 捕获错误并重试一次

  • wait_timeout当您知道查询之间已经过去了超过几秒时,抢先重新连接到服务器。

此错误也可能由于其他问题而发生。我会检查您是否使用持久连接,而不是一遍又一遍地连接到服务器。有时,连接过程,尤其是许多并发工作人员的连接过程,会导致大量网络开销,从而可能导致此类问题。

另外,有时,在生产、高交易量的服务器中,会发生奇怪的网络问题,并且这种情况可能只是偶尔发生,甚至在您的情况下似乎是通过环回接口发生的。

无论如何,最好编写您的代码,以便它可以优雅地处理错误并重试。通常,您可以将 SQL 查询包装在 a 中try..catch,以便在发生此错误时捕获它并重试。


查看完整回答
反对 回复 2023-09-15
  • 4 回答
  • 0 关注
  • 202 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信