今天测试出来了这个错误:
File "C:\test\webserver\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\test\webserver\env\lib\site-packages\django\db\backends\mysql\base.py", line 73, in execute
return self.cursor.execute(query, args)
File "C:\test\webserver\env\lib\site-packages\MySQLdb\cursors.py", line 206, in execute
res = self._query(query)
File "C:\test\webserver\env\lib\site-packages\MySQLdb\cursors.py", line 319, in _query
db.query(q)
File "C:\test\webserver\env\lib\site-packages\MySQLdb\connections.py", line 259, in query
_mysql.connection.query(self, query)
django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query')
数据库运转比较正常,后台使用的是Django框架。
最开始偶然遇到这种情况,以为是网络不稳定,毕竟公司的优秀的网络,下午不知道承载了多少人悠闲的时光。
我这个程序的场景是分出一个线程等待kafka端给到的任务结果。
不断测试后我发现,一旦任务返回的比较慢,就会产生这种问题。这种现象在不断的印证中让我意识到这是一种超时的错误。
仔细分析:
超时是我获得了本该失效的数据库连接,Django端的连接是复用的,即Django端有效但是用起来无效的连接。
也就是Django的超时时间 大于 数据库端的超时
所以从标黑部分的问题原因处给出三种解决方式:
- 针对连接是复用的
可以每次可能连接复用的情况下,将旧的连接断开,这样能保证使用的连接都是新创建的。
这种操作适用我这种用线程来等待,手握连接句柄比较长的情况。
# 关闭数据库连接
import django.db as ddb
ddb.close_old_connections()
- 针对Django的超时时间过长
首先需要知道数据库端的超时时间:
这两个才是需要关注的参数,网络读写的超时时间(单位 s)
net_read_timeout 30
net_write_timeout 60
事实上我们Django的连接超时时间不能超过以上的设置。
Django的连接默认超时时间是由 CONN_MAX_AGE 这个参数控制的,查询源码如下:
我们自然不能理解为默认超时时间是0,那么连接还有什么意义,朋友们也知道,如果永久不超时一般设置的是-1,而且永久不超时也没有意义啊!
为什么没有意义?
没有意义在于它不超时,但是数据库那边超时啊,这样留下来的只是报错了。
这里可能是把连接超时和连接关闭混淆了,难道永久不超时意味着永久不关闭吗?
肯定不是,正常操作数据库的时候,拿到连接,操作完就关闭了。
这里你复用在了线程中,迟迟等待没有关闭。那么久都超过数据库的设置了,所以连接失效。
所以可以想到CONN_MAX_AGE 这个参数默认值不是设置的时间,而是模式。
可以理解:
- 默认0时,随着连接的释放关闭连接。
- 手动设置值时候,长连接情况,根据超时时间来关闭连接。
随意我们就手动设置下这个参数的值就可以了:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'test', # 数据库名
'USER': 'root', # 账号
'PASSWORD': '123456', # 密码
'HOST': '127.0.0.1', # HOST
'PORT': '3306', # 端口
'CONN_MAX_AGE': 10,
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
}
}
- 增大数据库端的超时时间
set global net_read_timeout = 120;
set global net_write_timeout = 900;
这个问题搞懂了,各位同学可以根据自己实际问题的情况进行调整啊!