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

Posted

技术标签:

【中文标题】PDOException:数据包乱序。预期 0 收到 1. 数据包大小=23【英文标题】:PDOException: Packets out of order. Expected 0 received 1. Packet size=23 【发布时间】:2020-11-27 18:33:52 【问题描述】:

我有一个 Laravel Spark 项目,它使用 Horizo​​n 通过 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

或该错误的某些变体,其中数据包大小信息可能不同。

经过数小时/数天的调试和研究,我在 *** 和其他地方看到了许多帖子,这似乎表明可以通过做很多事情来解决这个问题,如下所列:

    在我的 database.php 配置中将 PDO::ATTR_EMULATE_PREPARES 设置为 true。这对问题完全没有影响,实际上引入了另一个问题,即整数被转换为字符串。

    DB_HOST 设置为127.0.0.1 而不是localhost,以便它使用TCP 而不是UNIX 套接字。同样,这没有任何效果。

    通过登录 mysql (MariaDB) 并运行 show variables like '%socket%';DB_SOCKET 设置为 MySQL 中列出的套接字路径,该路径将套接字路径列为 /run/mysqld/mysqld.sock。我还将DB_HOST 设置为localhost。这也没有效果。我确实注意到的一件事是 pdo_mysql.default_socket 变量设置为 /var/run/mysqld/mysqld.sock,我不确定这是否是问题的一部分?

    我已将/etc/mysql/mariadb.conf.d/50-server.cnf 中的 MySQL 配置设置大量增加到以下内容:

    key_buffer_size = 2048M max_allowed_packet = 2048M max_connections = 1000 thread_concurrency = 100 query_cache_size = 256M

我必须承认,更改这些设置是最后的手段/抓住稻草类型的场景。然而,这确实在一定程度上缓解了这个问题,但并没有完全解决它,因为 MySQL 在 99% 的情况下仍然会失败,尽管是在后期。

就队列而言,我总共有 1,136 workers 分成 6 个主管/队列,它们都是通过 Laravel Horizo​​n 处理的,它作为守护进程运行。

我也再次使用 Laravel Websockets PHP 包进行广播,它也作为守护进程运行。

我目前的环境配置如下(敏感信息省略)。

APP_NAME="App Name"
APP_ENV=production
APP_DEBUG=false
APP_KEY=thekey
APP_URL=https://appurl.com
LOG_CHANNEL=single

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=databse
DB_USERNAME=username
DB_PASSWORD=password

BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
QUEUE_CONNECTION=redis
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=name@email.com
MAIL_PASSWORD=password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=name@email.com
MAIL_FROM_NAME="$APP_NAME"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION="us-east-1"
AWS_BUCKET=

PUSHER_APP_ID=appid
PUSHER_APP_KEY=appkey
PUSHER_APP_SECRET=appsecret
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="$PUSHER_APP_KEY"
MIX_PUSHER_APP_CLUSTER="$PUSHER_APP_CLUSTER"

AUTHY_SECRET=

CASHIER_CURRENCY=usd
CASHIER_CURRENCY_LOCALE=en
CASHIER_MODEL=App\Models\User
STRIPE_KEY=stripekey
STRIPE_SECRET=stripesecret

# ECHO SERVER
LARAVEL_WEBSOCKETS_PORT=port

服务器设置如下:

最大文件上传大小:1024 最长执行时间:300 PHP 版本:7.4 MariaDB 版本: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。仍然没有乐趣。

最后,哪个事件、作业或侦听器正在运行似乎并不重要,因为错误发生在随机事件上。所以,不确定它是特定于代码的,但很可能是。

希望我已经提供了足够的背景和详细信息来获得一些帮助,但如果我遗漏了什么,请告诉我,我会将其添加到问题中。谢谢。

【问题讨论】:

附加信息请求。 MySQL 主机服务器上有任何 SSD 或 NVME 设备吗?在 pastebin.com 上发布并分享链接。从您的 SSH 登录根目录中,文本结果为:B) SHOW GLOBAL STATUS;至少 24 小时正常运行时间后 C) 显示全局变量; D) 显示完整的处理程序; F) 显示 ENGINE INNODB 状态;和 可选的非常有用的信息,如果可用,包括 - htop 或 top 用于大多数活动应用程序,ulimit -a 用于 Linux/Unix 限制列表,iostat -xm 5 3 用于按设备和核心/cpu 计数的 IOPS,用于服务器工作负载调整分析提供建议。 嘿@WilsonHauck,感谢您提供的信息。是的,有一个 800GB SSD。以下是您请求的转储:B:pastebin.com/CMiF24Ns C:pastebin.com/kdVX5Rvv D:pastebin.com/JJQQieP1 F:pastebin.com/7ACQmdc9 htop:imgur.com/a/DH5OQqj ulimit:pastebin.com/Z180YAv0iostat:pastebin.com/38RYuUBn 感谢您的关注。跨度> Gareth 显示全局变量;发布的只有最后 ~ 120 行全局变量。 SHOW GLOBAL VARIABLES 通常有 400 多行; iostat 用于单组输出。 iostat -xm 5 3 通常有一个摘要和两个以 5 秒为间隔的循环。 htop 表示 MEM 约为 96M。谢谢 嘿 Wilson,这里是 iostat 输出:pastebin.com/jDwXMje6 我不确定如何从 SHOW GLOBAL VARIABLES 中输出所有变量,因为 MySQL 中的命令行似乎截断了它,只显示最后 120 个左右。 Gareth 你可以分两步把它们捡起来。显示全局变量,其中 variable_name "l%";并分享 2 个 pastebin.com 链接。谢谢 【参考方案1】:

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

my.cnf,我补充说:

max_allowed_packet=200M

然后service mysql stopservice mysql start,它工作了:)

【讨论】:

【参考方案2】:

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

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

【讨论】:

这对我也有用,即使我不得不承认我不确定为什么需要这样做。【参考方案3】:

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

【讨论】:

【参考方案4】:

MySQL 8 - 在mysql.cnf,禁用所有这些 ->

# For error - ( MySQL server has gone away )
#wait_timeout=90
#net_read_timeout=90
#net_write_timeout=90
#interactive_timeout=300

看来要帮帮我。

【讨论】:

以上是关于PDOException:数据包乱序。预期 0 收到 1. 数据包大小=23的主要内容,如果未能解决你的问题,请参考以下文章

我在连接到数据库时遇到错误使用节点包 mysql v2.16.0 错误:数据包乱序。得到:80 预期:0

协议数据包乱序

调用 MySQL 存储过程时出现数据包乱序错误

读取tcp包乱序

MySQL java jdbc MySQLNonTransientConnectionException:得到的数据包乱序

分析RTP流丢包乱序