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

新手上路,请多包涵

我有一个 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 和其他地方看到了很多帖子,这些帖子似乎表明可以通过做一些事情来解决这个问题,如下所列:

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

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

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

  4. 我已将 /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 Horizon 处理。

我也再次使用 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
  • 玛丽亚数据库 版本:10.3.22

我检查了 MySQL 服务器崩溃/消失时的所有日志(见下文),MySQL 日志中什么也没有。没有任何错误。我也没有看到任何东西:

  • /var/log/nginx/error.log
  • /var/log/nginx/access.log
  • /var/log/php7.4-fpm.log

我目前仍在挖掘和调试,但现在,我被难住了。这是我第一次遇到这个错误。

这可能是因为访问数据库(读/写)速度太快了吗?

关于队列如何工作的一些信息。

  1. 我有一个初始控制器,可以将作业分派到队列中。
  2. 一旦这个工作完成,它就会触发一个事件,然后开始按顺序运行其他几个监听器/事件的过程,所有这些都取决于在新事件被触发和新的监听器/工作开始工作之前完成的先前工作。
  3. 总共广播了 30 个事件。
  4. 总共有 30 名听众。
  5. 总共有5个职位。

这些都基于运行的侦听器/作业及其触发的事件按顺序工作。

我还监视了 laravel.log 实时,当崩溃发生时,根本没有任何记录。虽然,我偶尔会得到 production.ERROR: Failed to connect to Pusher. 无论 MySQL 是否崩溃,所以我认为这与这个问题没有任何关系。

我什至注意到 Laravel API 速率限制正在被触及,所以我确保将它从 60 大幅增加到 500。仍然没有快乐。

最后,运行哪个 Event、Job 或 Listener 似乎并不重要,因为错误是随机发生的。因此,不确定它是特定于代码的,但很可能是。

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

原文由 Gareth Daine 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
1 个回答

对我来说,修复它的是增加最大数据包大小。

my.cnf 中,我添加了:

 max_allowed_packet=200M

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

原文由 obe 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏