内容简介:查询mysql全局变量下面用Django复现下次问题:那么以上问题就基本说明了是空闲时间过长导致的错误。
问题
在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复现下次问题:
-
将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
方法。
django.db.close_old_connections
题外话实际上②所述情况最好从根本上解决处理慢的问题,也可以换作异步处理,从根本上解决问题。
以上所述就是小编给大家介绍的《Django数据库连接丢失问题 原 荐》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MySQL root 密码丢失重置
- kafka consumer防止数据丢失
- MongoDB 副本集丢失数据的测试
- 苹果CloudKit出现问题:部分应用数据丢失
- React中this丢失的解决方法
- vuex页面刷新数据丢失的解决办法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Operating System Algorithms
Nathan Adams、Elisha Chirchir / CreateSpace Independent Publishing Platform / 2017-4-21 / USD 39.15
Operating System Algorithms will walk you through in depth examples of algorithms that you would find in an operating system. Selected algorithms include process and disk scheduling.一起来看看 《Operating System Algorithms》 这本书的介绍吧!