详解多线程Django程序耗尽数据库连接的问题


Posted in Python onOctober 08, 2018

Django的ORM是非常好用的,哪怕不是做Web项目也值得一用,所以网上也可以找到不少使用 Django 开发非Web项目的资料,因为除了ORM之个,命令行、配置文件等组件也非常好用。

最近用这种方式开发了一个非Web项目,而且是多线程的。有N个工作线程从DB中获取jobs,并把结果写回DB。简单来说就是这样。

项目运行一段时间后,发现数据库连接耗尽了,幸好内存大,然后一直往上调,最后连接数都上九千多一万了。耗尽连接数的时候,PostgreSQL 会出现类似这样的错误:

FATAL: remaining connection slots are reserved for non-replication superuser connections

然后就各种看文档、代码,找问题,其中艰难略下不表,最后大概是这么些个知识点:

  1. Django里的数据库连接是放在线程的 local() 实例中的。
  2. 任何时候,需要一个数据库连接的话,Django就会创建一条出来,或者用本线程已有的那条。
  3. 如果是Web项目,在请求结束的时候,Django会去关闭掉连接。是的,没有连接池。
  4. 因为我们是非Web项目,所以不存在请求结束事件,所以一直没的关闭连接。但本来这个应该也不会造成问题的,因为没关闭就一直用呗,但不知道哪里出了问题,会出现连接泄漏,所以连接数据会一直增长。

最后的解决方案是找时机主动关闭数据库连接,具体到我们项目,就是每次工作线程完成一个任务后,就把它相关的连接关掉,因为我们用的是 ThreadPoolExecutor ,所以Django很容易做到这一点。

重点代码如下:

from django.db import connections

def on_done(future):
  # 因为每一个线程都有一个 connections,所以这里可以调用 close_all(),把本线程名下的所有连接关闭。
  connections.close_all()

def main():
  # ...
  with ThreadPoolExecutor() as executor:
    while True:
      future = executor.submit(do, get_a_job())
      future.add_done_callback(on_done)

主动关闭后,数据库连接数降到与工作线程数相近,并保持稳定。

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

Python 相关文章推荐
python调用java的Webservice示例
Mar 10 Python
Python中变量交换的例子
Aug 25 Python
Python使用修饰器执行函数的参数检查功能示例
Sep 26 Python
R语言 vs Python对比:数据分析哪家强?
Nov 17 Python
tensorflow实现简单的卷积神经网络
May 24 Python
Python Socket编程之多线程聊天室
Jul 28 Python
Python简单过滤字母和数字的方法小结
Jan 09 Python
pytorch:model.train和model.eval用法及区别详解
Feb 20 Python
解决python虚拟环境切换无效的问题
Apr 30 Python
如何在mac版pycharm选择python版本
Jul 21 Python
python中Pexpect的工作流程实例讲解
Mar 02 Python
Python可视化神器pyecharts绘制水球图
Jul 07 Python
JSON文件及Python对JSON文件的读写操作
Oct 07 #Python
Python实现登陆文件验证方法
Oct 06 #Python
python对日志进行处理的实例代码
Oct 06 #Python
浅析Python函数式编程
Oct 06 #Python
Python实现iOS自动化打包详解步骤
Oct 03 #Python
Python中GIL的使用详解
Oct 03 #Python
Python线程同步的实现代码
Oct 03 #Python
You might like
解析php多线程下载远程多个文件
2013/06/25 PHP
php使用GD2绘制几何图形示例
2017/02/15 PHP
js 页面传参数时 参数值含特殊字符的问题
2009/12/13 Javascript
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
基于jQuery实现美观且实用的倒计时实例代码
2015/12/30 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
2016/07/12 Javascript
浅谈在js传递参数中含加号(+)的处理方式
2016/10/11 Javascript
微信小程序 火车票查询实例讲解
2016/10/17 Javascript
利用fecha进行JS日期处理
2016/11/21 Javascript
Vue.js上下滚动加载组件的实例代码
2017/07/17 Javascript
js最简单的双向绑定实例讲解
2018/01/02 Javascript
React 源码中的依赖注入方法
2018/11/07 Javascript
vue输入节流,避免实时请求接口的实例代码
2019/10/30 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
vue 限制input只能输入正数的操作
2020/08/05 Javascript
vue界面发送表情的实现代码
2020/09/11 Javascript
[01:00:14]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第二场 2月28日
2021/03/11 DOTA
在Python中用get()方法获取字典键值的教程
2015/05/21 Python
Python中字典创建、遍历、添加等实用操作技巧合集
2015/06/02 Python
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
Python FTP两个文件夹间的同步实例代码
2018/05/25 Python
Python 爬取携程所有机票的实例代码
2018/06/11 Python
Python根据成绩分析系统浅析
2019/02/11 Python
Python基于stuck实现scoket文件传输
2020/04/02 Python
css3 media 响应式布局的简单实例
2016/08/03 HTML / CSS
AmazeUI中模态框的实现
2020/08/19 HTML / CSS
粉红色的鲸鱼:Vineyard Vines
2018/02/17 全球购物
自1926年以来就为冰岛保持温暖:66°North
2020/11/27 全球购物
创先争优标语
2014/06/27 职场文书
2014年度安全生产目标管理责任书
2014/07/25 职场文书
民主生活会批评与自我批评总结
2014/10/17 职场文书
虎兄虎弟观后感
2015/06/12 职场文书
校园开放日新闻稿
2015/07/17 职场文书
浅谈redis五大数据结构和使用场景
2021/04/12 Redis
小程序实现悬浮按钮的全过程记录
2021/10/16 HTML / CSS
sql server 累计求和实现代码
2022/02/28 SQL Server