详解多线程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实现从ftp服务器下载文件的方法
Apr 30 Python
Python实现压缩与解压gzip大文件的方法
Sep 18 Python
Python正则表达式分组概念与用法详解
Jun 24 Python
zookeeper python接口实例详解
Jan 18 Python
分享一下Python数据分析常用的8款工具
Apr 29 Python
Python中交换两个元素的实现方法
Jun 29 Python
微信公众号token验证失败解决方案
Jul 22 Python
使用Python自动生成HTML的方法示例
Aug 06 Python
Python垃圾回收机制三种实现方法
Apr 27 Python
python实现数字炸弹游戏
Jul 17 Python
python3环境搭建过程(利用Anaconda+pycharm)完整版
Aug 19 Python
教你如何用python操作摄像头以及对视频流的处理
Oct 12 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几个数学计算的内部函数学习整理
2011/08/06 PHP
PHP动态创建Web站点的方法
2011/08/14 PHP
php分页示例分享
2014/04/30 PHP
PHP中常见的缓存技术实例分析
2015/09/23 PHP
php curl模拟post请求和提交多维数组的示例代码
2015/11/19 PHP
php批量修改表结构实例
2017/05/24 PHP
传智播客学习之JavaScript基础篇
2009/11/13 Javascript
文本框中,回车键触发事件的js代码[多浏览器兼容]
2010/06/07 Javascript
jQuery源码分析-01总体架构分析
2011/11/14 Javascript
jquery制作搜狐快站页面效果示例分享
2014/02/21 Javascript
express的中间件basicAuth详解
2014/12/04 Javascript
浅析Javascript中“==”与“===”的区别
2014/12/23 Javascript
JavaScript中split与join函数的进阶使用技巧
2016/05/03 Javascript
微信小程序request请求后台接口php的实例详解
2017/09/20 Javascript
JS简单实现查看文档创建日期、修改日期和文档大小的方法示例
2018/04/08 Javascript
JSON.stringify()方法讲解
2019/01/31 Javascript
Vue实现固定定位图标滑动隐藏效果
2019/05/30 Javascript
Express 配置HTML页面访问的实现
2020/11/01 Javascript
python读取二进制mnist实例详解
2017/05/31 Python
Python使用matplotlib和pandas实现的画图操作【经典示例】
2018/06/13 Python
python实现几种归一化方法(Normalization Method)
2019/07/31 Python
python Web flask 视图内容和模板实现代码
2019/08/23 Python
使用pandas 将DataFrame转化成dict
2019/12/10 Python
如何使用python传入不确定个数参数
2020/02/18 Python
Python中使用threading.Event协调线程的运行详解
2020/05/02 Python
python mysql自增字段AUTO_INCREMENT值的修改方式
2020/05/18 Python
Python读取多列数据以及用matplotlib制作图表方法实例
2020/09/23 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
浅谈CSS3特性查询(Feature Query: @supports)功能简介
2017/07/31 HTML / CSS
教育技术职业规划范文
2014/03/04 职场文书
2014基层党员批评与自我批评范文
2014/09/24 职场文书
学习保证书100字
2015/02/26 职场文书
公司员工违纪检讨书
2015/05/05 职场文书
入党积极分子党小组意见
2015/06/02 职场文书
小学运动会入场词
2015/07/18 职场文书
Python编程中内置的NotImplemented类型的用法
2022/03/23 Python