其他分享
首页 > 其他分享> > Django ORM 连接超时的坑

Django ORM 连接超时的坑

作者:互联网

Django ORM 连接超时的坑

数据库链接丢失异常

django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query')

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

Django中的数据库连接

Django程序接受到请求之后,在第一访问数据库的时候会创建一个数据库连接,直到请求结束,关闭连接。下次请求也是如此。因此,这种情况下,随着访问的并发数越来越高,就会产生大量的数据库连接。即,没收到一次请求,django就会建立一个数据库连接

解决方案

django关闭连接流程

对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实现特定事件时执行此方法(类似于 触发器),两个特定事件是请求开始和请求结束。

如果报错的是在一次请求中,所以此法通常无效,仅仅是实现每个请求关闭并重新建立连接。

解决原理:

在每一次查询操作前,通过调用close_old_connections()主动关闭闲置连接,主动关闭闲置连接,当再次操作数据库,会自动建立新的连接。

具体方法

from django.db import close_old_connections

def func(request):
    models.User.objects.filter(name='xxx')
    
    time.sleep(9*60*60)		# 模拟执行长时间耗时操作,时间超过MySQL的 wait_timeout
    
    close_old_connections()	# 先手动关闭无效时间
    models.User.objects.filter(name='xxx')	# 再进行查询

标签:old,请求,数据库,Django,connections,ORM,close,超时,连接
来源: https://www.cnblogs.com/xiongsheng/p/15881799.html