问题

在Django中使用mysql偶尔会出现数据库连接丢失的情况,错误通常有如下两种
1. OperationalError: (2006, 'MySQL server has gone away')
1. OperationalError: (2013, 'Lost connection to MySQL server during query')

查询mysql全局变量SHOW GLOBAL VARIABLES;可以看到wait_timeout,此变量表示连接空闲时间。如果客户端使用一个连接查询多次数据库,如果连续查询则没有问题,如果查询几次后停顿超过wait_timeout后再次查询就会出现数据库连接丢失。

复现

下面用Django复现下次问题:

  1. 将mysql的wait_timeout设置为10秒,然后进入django shell模拟查询(以下错误信息只保留了部分)
In[1]:import time
In[2]:from django.contrib.auth.models import User
In[3]:list(User.objects.filter(id=1))
Out[3]:[<User: admin>]
In[4]:time.sleep(15) # 模拟比较慢的代码(其中没有查询数据库的代码),或者空闲什么都不操作一段时间,此时间要比`wait_timeout`大一些
list(User.objects.filter(id=1))
Traceback (most recent call last):File "<ipython-input-4-3574ae8220ee>", line 1, in <module>list(User.objects.filter(id=1))File "/usr/lib/python3.6/site-packages/pymysql/connections.py", line 1037, in _read_bytesCR.CR_SERVER_LOST, "Lost connection to MySQL server during query")
django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query')
复制代码

寻求

那么以上问题就基本说明了是空闲时间过长导致的错误。
django为了减少不必要的数据库连接、关闭,复用了数据库连接,当开始一个请求后建立一个连接池存放连接,之后此次请求都复用一个连接。那猜测就是django保存连接的比wait_timeout长了,如果保存时间短一些就可以重新建立连接避免此错误了。 没错,官方文档也已经说明了此问题,设置数据库 CONN_MAX_AGE参数,示例:

DATABASES = {"default": {'ENGINE': 'django.db.backends.mysql','NAME': '','USER': '','PASSWORD': '','HOST': '','CONN_MAX_AGE': 9  # 比wait_timeout小一些}
}
复制代码

当我们测试后却发现,事情并非想想中那么简单。为何错误依旧出现?这一切的背后, 是人性的扭曲还是道德的沦丧?敬请收看下节《突破》。

突破

对django源码中CONN_MAX_AGE进行了一番搜索,顺藤摸瓜发现了django关闭失效连接的方法django.db.close_old_connections()

# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):for conn in connections.all():conn.close_if_unusable_or_obsolete()signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)
复制代码

重点在最后两行,通过signal实现特定事件时执行此方法,两个特定事件顾名思义是请求开始和请求结束。而我们报错的是在一次请求中,所以此法通常无效,仅仅是实现每个请求关闭并重新建立连接。

解决

复现问题的django shell不要关闭,继续执行如下代码:

In[5]:from django.db import close_old_connections
In[6]:close_old_connections()
In[7]:list(User.objects.filter(id=1))
Out[7]: [<User: admin>]
复制代码

调用django.db.close_old_connections后再次查询就没有错误了。 那么我们要避免此错误就要执行每个数据库查询前调用django.db.close_old_connections方法。

  1. 一般情况不会出现此类问题,因为一个请求中不间断进行数据库查询,无需每个请求调用此方法,杞人忧天。
  2. 有时候一个请求中数据量较大,会查询数据库后进行一段时间其他(不涉及数据库)处理,比如先查询一些数据,然后将数据处理、生成excel、保存文件并生成url。已知此过长需要非常长时间,那么最终url保存数据库就最好先调用django.db.close_old_connections防止连接丢失

题外话 实际上②所述情况最好从根本上解决处理慢的问题,也可以换作异步处理,从根本上解决问题。

转载于:https://juejin.im/post/5c25bbd9f265da615304d5b6

Django数据库连接丢失问题相关推荐

  1. django html数据库连接,Django数据库连接的问题

    多线程运行项目.有N个工作线程从DB中获取jobs,并把结果写回DB. 项目运行一段时间后,发现数据库连接耗尽了,幸好内存大,然后一直往上调,最后连接数都上8000多.耗尽连接数的时候,postgre ...

  2. Django数据库连接池(mysql)

    都知道django每次请求都会连接数据库和释放数据库连接.Django为每个请求使用新的数据库连接.一开始这个方法行得通.然而随着服务器上的负载的增加,创建/销毁连接数据库开始花大量的时间.要避免这个 ...

  3. Django 数据库连接使用

    整个项目已经放在Github上, 随时更新, 项目地址 Django Model 每一个Django Model都继承自django.db.models.Model 在Model当中每一个属性attr ...

  4. django mysql连接超时设置_坑(一)—— Django ORM 连接超时的坑

    问题 数据库链接丢失异常 django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query' ...

  5. Python+Django电影推荐系统搭建

    文章目录 1. 新建虚拟环境 2. 数据库设置 2.1 安装PostGreSQL 2.2 为MovieGEEK创建数据库 2.3 安装Python数据库驱动程序 2.4 配置Django数据库连接以连 ...

  6. [Python + Django] Web在线考试管理系统设计及代码实现

    本文最终实现一个Web在线考试管理系统,可作为Python Web,Django的练手项目,也可以作为计算机毕设参考项目. 源码获取方式:[Django]pythonweb学生信息及考试管理系统毕业设 ...

  7. python 数据库连接池DBUtils

    python 数据库连接池DBUtils 0x00 简述 0x01 摘要 0x02 模块 0x03 下载及安装 1.下载 2.安装 0x04 SimplePooledDB 0x05 SteadyDB ...

  8. [Python+Django]Web学生信息管理系统数据库设计及系统实现

    本文我们完成数据的设计,并通过Django框架完成数据库构建同时利用Django框架模式实现学生信息管理系统的功能. 简单的包装下毕设应该没问题了. Python,Mysql,Pycharm的安装本文 ...

  9. [PHP] Laravel常见报错总结(持续更新)

    >>报错:「Can't swap PDO instance while within transaction」 通过查询 Laravel 源代码,可以确认异常是在 setPdo 方法中抛出 ...

最新文章

  1. 「悟道」来了!大规模预训练模型交流论坛开启报名
  2. 增加堆内存的大小 - 提防眼镜蛇效应
  3. 【期望】守卫挑战(金牌导航 期望-9)
  4. App 运营的指标具体都有哪些?(四)
  5. ARMA模型的性质 1
  6. 作者:景志刚(1977-),男,就职于中国人民银行征信中心数据部
  7. 致敬F1七冠王!Redmi K50电竞版邀请函曝光 打造掌上梦幻跑车
  8. 【干货】联邦学习在腾讯微视广告投放中的实践
  9. python mysql创建表日期型_python 操作mysql,按照当前时间建立表,无法创建表..
  10. linux服务器上配置二级域名
  11. 计算机网络有个红叉怎么办,笔记本电脑右下角网络出现红叉的解决办法
  12. mysql中的mysql数据库不见了
  13. mac多屏幕切换快捷键
  14. Jsp中分页功能的实现
  15. 粉丝福利 | 秒 get 支付宝同款扫码组件
  16. Eclipse无法启动
  17. 利用Python进行数据分析_Wes McKinney著_唐学韬译_笔记
  18. 白门柳-刘斯奋有声小说
  19. C语言free空空指针,dmc: Dynamic Memory Check (DMC) , 解决C语言空指针、悬空指针、越界访问、野指针问题的一个方案。...
  20. 目标检测算法——单次目标检测器

热门文章

  1. 聚集索引与非聚集索引及其查询效率【转载】
  2. 第10章-Vue.js 项目实战
  3. VMware中让虚拟机支持虚拟化
  4. Android之SwipeRefreshLayout下拉刷新组件
  5. pl/sql 中变量定义范围的小例子:
  6. c语言中有关逗号表达式
  7. 实战MongoDB-Replication之Master-Slave
  8. 日本新年传统习俗介绍(一)
  9. LNK2026 module unsafe for SAFESEH image
  10. PySpark+Windows开发环境的搭建