django使用django-apscheduler为什么总是提示2006,server has gone away

发布时间 2023-05-08 10:06:15作者: 虫王戮蛊

    最近使用django在做一个定时任务场景,采用的是gjango-apscheduler模块,出现了一个问题,我的定时场景是每天的8点和17点启动一个任务,但是每次只能第一次生效,第二天就会出现2006,server has gone away这个错误,看到错误的第一反应就是数据库服务挂了??因为看详情是运行到ORM的查表处就报错了,做了监控也没问题,后面经过查询资料知道了,原来是因为apscheduler的定时任务的数据库连接超时导致,超时了之后不会自动关闭数据库连接,导致查表失败。

Django 跑批任务错误 (2006, ‘MySQL server has gone away’) 和 MySQL server has gone away 设置 mysql 连接自动断开,初步判断是由于长时间没有操作数据库导致连接被数据库断开而导致的报错。

因为 Mysql 的 wait_timeout 默认是8个小时,而我项目中定时任务是24小时执行一次,且一次执行需要的时间只需要几秒钟,当第一次执行的时候,Django 和 Mysql 建立的一个连接会自动保持8小时的连接,但是8小时之后 Mysql 会断开这个连接,而第二次执行任务的时候Django 还用上次的连接去连接 mysql,因此得到一个 gone away 的结果。

4. 解决方案
一、加长 wait_timeout

在数据库的配置文件内配置超时时间 wait_timeout,还有设置 max_allow_pocket 的(对于 sql 语句长的、数据量大的有效),网上有很多教程,这种方案增加 mysql 的资源开销,此处不推荐。

二、修改 Django-apscheduler 源码

自测有效

找到 ${python_path}/lib/python3.7/site-packages/django_apscheduler/jobstores.py 文件

找到 def _get_jobs(self, **filters) 函数(大约在 288 行)

在这个函数里加一行代码 db.close_old_connections() 关掉过期的旧连接,建立新连接