Django/Mysql异步错误 “The client was disconnected by the server because of inactivity”

标签 django mysql-8.0

我正在使用连接到 MySQL 8.0.30 数据库的 Django 4.2。服务器是 nginx ,带有gunicorn(3个工作人员)并使用WSGI。

我正在为需要异步运行的函数运行 asyncio,因为它由异步 API 代理使用,但在这里我只是直接从 View 调用,因此它是直接且短暂的:

from django.db import connection
import asyncio

example_object = asyncio.run(make_query(name))

async def make_query(request, name):
    object = await ModelExample.objects.filter(name=name).afirst()
    return object

我在 afirst() 查询执行时遇到以下错误: [4031] 由于不活动,客户端已被服务器断开连接。请参阅 wait_timeout 和 Interactive_timeout 以配置此行为

最初代码工作正常,错误仅在几个小时(可能 8 小时)后开始。我可以通过重新启动(nginx)错误来临时修复它。这是一个低流量网站,因此该功能很可能每天只执行一次。

因为它需要 8 小时不活动,所以复制或调试它并不容易。


我尝试过的:

Django 层:

根据我的理解,Django 总是打开一个连接,执行一个查询,然后关闭一个连接。 这也应该发生在 WSGI 中,但连接空闲表明情况并非如此。 所以我尝试了:

  1. 在 asyncio.run 之前添加 close_old_connections()
  2. 在asyncio.run之后添加connection.close()
  3. CONN_HEALTH_CHECKS选项设置为True,希望“如果健康检查失败,将重新建立连接而不会导致请求失败”
  4. 在 Django 设置文件中将 CONN_MAX_AGE 从默认的 0 更改为“None”,根据 Django 文档,这意味着无限的持久数据库连接。

没有任何效果。

如果这是 Django 问题,那么我最后的猜测是在使用 MySQL 时“afirst()”(在 Django 4.1 中添加)的错误。

MySQL层:

发现一些报告将此问题归因于 MySQL(也发生在 Wordpress 和 PHP 应用程序中),所以我尝试了:

  1. 增加 MySQL 配置文件中的 wait_timeout 值和 interactive_timeout 变量。 SHOW VARIABLES 命令显示它们当前确实设置为 31536000。
  2. Mysql 8.0.32 release notes这里似乎提到了这个问题: “每当连接因不活动而终止时,线程池插件仅打印一条有关连接超时的通用消息;这通常会使分析此类超时变得比必要的更加困难。新的 INFO_LEVEL 消息清楚地表明连接已超时由于线程池中不活动而被终止,以及用于做出此确定的超时值。(错误#34767607)“

所以我更新了 MySQL,希望能获得更多信息,如果我这样做了,我会告诉你的。

请让我知道您对如何调试此问题的想法、想法或建议! 提前致谢。

最佳答案

为 future 使用 DigitalOcean 时可能遇到相同问题的人解答此问题。

看起来配置 MySQL 的初始方法是正确的,但它实际上并未应用于数据库。如果您使用的是 DigitalOcean,通过 SSH 将配置应用到 Droplet 并不对应于数据库集群中的实际配置。

要解决此问题,您需要使用 DigitalOcean 的 API 来配置数据库。对变量进行以下更改似乎可以解决我的问题:

  • connect_timeout 为 60
  • interactive_timeout 为 604800
  • wait_timeout 为 2147483
  • net_read_timeout 为 120

使用此配置,Django 的异步功能应该可以在低流量网站中正常工作。 Ofc 可能会有所不同,具体取决于您的设置和要求。

关于Django/Mysql异步错误 “The client was disconnected by the server because of inactivity”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76567076/

相关文章:

django - 使用序列化程序 Django (DRF) 创建对象

python - Django 如何知道在 urls.py 中使用什么 'pk' ?

mysql - 在 Mysql 中检索 JSON 数组内的 Json 数据值

django:mysql:error(1045, "Access denied for user ' root' @'localhost' (使用密码: NO)")

php - Laravel 迁移,hasColumn 方法失败

python - BootstrapError 参数 "form"应包含有效的 Django 表单

django - 排除特定 HTTP 方法的 swagger 文档

django - 通过 Django shell 添加文件

mysql - 如何在mysql中将日期时间分组为3小时的间隔

mysql - 如何查询mysql json列中的对象的对象