Django数据库连接丢失问题的解决方法


Posted in Python onDecember 29, 2018

问题

在Django中使用mysql偶尔会出现数据库连接丢失的情况,错误通常有如下两种

OperationalError: (2006, 'MySQL server has gone away')
OperationalError: (2013, 'Lost connection to MySQL server during query')

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

复现

下面用Django复现下次问题:

将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_bytes
    CR.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方法。

一般情况不会出现此类问题,因为一个请求中不间断进行数据库查询,无需每个请求调用此方法,杞人忧天。

有时候一个请求中数据量较大,会查询数据库后进行一段时间其他(不涉及数据库)处理,比如先查询一些数据,然后将数据处理、生成excel、保存文件并生成url。已知此过长需要非常长时间,那么最终url保存数据库就最好先调用django.db.close_old_connections防止连接丢失

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现的各种排序算法代码
Mar 04 Python
python实现同时给多个变量赋值的方法
Apr 30 Python
Django 添加静态文件的两种实现方法(必看篇)
Jul 14 Python
python在ubuntu中的几种安装方法(小结)
Dec 08 Python
python 移动图片到另外一个文件夹的实例
Jan 10 Python
浅谈pytorch池化maxpool2D注意事项
Feb 18 Python
在Mac中PyCharm配置python Anaconda环境过程图解
Mar 11 Python
Python openpyxl 插入折线图实例
Apr 17 Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
Jun 02 Python
python中查看.db文件中表格的名字及表格中的字段操作
Jul 07 Python
python自动化测试三部曲之unittest框架的实现
Oct 07 Python
Django操作cookie的实现
May 26 Python
Python Cookie 读取和保存方法
Dec 28 #Python
Python编程flask使用页面模版的方法
Dec 28 #Python
Python编程中flask的简介与简单使用
Dec 28 #Python
Python3 Post登录并且保存cookie登录其他页面的方法
Dec 28 #Python
Python3 使用cookiejar管理cookie的方法
Dec 28 #Python
Python编程在flask中模拟进行Restful的CRUD操作
Dec 28 #Python
python获取服务器响应cookie的实例
Dec 28 #Python
You might like
外媒评选出10支2020年最受欢迎的Dota2战队
2021/03/05 DOTA
PHP使用者状态管理功能的应用
2006/10/09 PHP
使用PHP获取当前url路径的函数以及服务器变量
2013/06/29 PHP
YII实现分页的方法
2014/07/09 PHP
浅谈php中的循环while、do...while、for、foreach四种循环
2016/11/05 PHP
greybox——不开新窗口看新的网页
2007/02/20 Javascript
JS 实现双色表格实现代码
2009/11/24 Javascript
Textarea根据内容自适应高度
2013/10/28 Javascript
jquery使用each方法遍历json格式数据实例
2015/05/18 Javascript
详解JavaScript中shift()方法的使用
2015/06/09 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
Vue实现购物车的全选、单选、显示商品价格代码实例
2019/05/06 Javascript
Vue2.0 ES6语法降级ES5的操作
2020/10/30 Javascript
Python中的装饰器用法详解
2015/01/14 Python
如何在Python中编写并发程序
2016/02/27 Python
Python聊天室程序(基础版)
2018/04/01 Python
python3.6数独问题的解决
2019/01/21 Python
浅谈PYTHON 关于文件的操作
2019/03/19 Python
Python基于机器学习方法实现的电影推荐系统实例详解
2019/06/25 Python
tensorflow求导和梯度计算实例
2020/01/23 Python
python正则过滤字母、中文、数字及特殊字符方法详解
2020/02/11 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
Gtech官方网站:地毯清洁器、吸尘器及园艺设备
2018/05/23 全球购物
Linux不知道文件后缀名怎么判断文件类型
2012/04/26 面试题
介绍下Lucene建立索引的过程
2016/03/02 面试题
红旗方阵解说词
2014/02/12 职场文书
人事专员的职责
2014/02/26 职场文书
党组织公开承诺书
2014/03/29 职场文书
民主生活会剖析材料
2014/09/30 职场文书
副校长个人对照检查材料思想汇报
2014/10/04 职场文书
交通事故协议书范本
2014/11/18 职场文书
自愿离婚协议书范本
2015/01/26 职场文书
2016年感恩节活动总结大全
2016/04/01 职场文书
详解CocosCreator项目结构机制
2021/04/14 Javascript
教你如何用Python实现人脸识别(含源代码)
2021/06/23 Python
小程序实现侧滑删除功能
2022/06/25 Javascript