Django Lost connection to MySQL server during query

今天测试出来了这个错误:

  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的超时时间 大于 数据库端的超时
所以从标黑部分的问题原因处给出三种解决方式:

  1. 针对连接是复用的

可以每次可能连接复用的情况下,将旧的连接断开,这样能保证使用的连接都是新创建的。
这种操作适用我这种用线程来等待,手握连接句柄比较长的情况。

# 关闭数据库连接
import django.db as ddb
ddb.close_old_connections()
  1. 针对Django的超时时间过长

首先需要知道数据库端的超时时间:
数据库端的超时时间
这两个才是需要关注的参数,网络读写的超时时间(单位 s)
net_read_timeout 30
net_write_timeout 60
事实上我们Django的连接超时时间不能超过以上的设置。

Django的连接默认超时时间是由 CONN_MAX_AGE 这个参数控制的,查询源码如下:
Django的超时默认值
我们自然不能理解为默认超时时间是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'"
        }
    }
}
  1. 增大数据库端的超时时间
set global net_read_timeout = 120;
set global net_write_timeout = 900;

这个问题搞懂了,各位同学可以根据自己实际问题的情况进行调整啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值