详解多线程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开发环境搭建
Dec 16 Python
python 使用get_argument获取url query参数
Apr 28 Python
Python文本统计功能之西游记用字统计操作示例
May 07 Python
python 将json数据提取转化为txt的方法
Oct 26 Python
Python3.4学习笔记之 idle 清屏扩展插件用法分析
Mar 01 Python
使用Python计算玩彩票赢钱概率
Jun 26 Python
pip install python 快速安装模块的教程图解
Oct 08 Python
python return逻辑判断表达式实现解析
Dec 02 Python
python操作cfg配置文件方式
Dec 22 Python
Python键鼠操作自动化库PyAutoGUI简介(小结)
May 17 Python
python 还原梯度下降算法实现一维线性回归
Oct 22 Python
Sentry错误日志监控使用方法解析
Nov 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文件上传表单摘自drupal的代码
2011/02/15 PHP
php实现简单的守护进程创建、开启与关闭操作
2019/08/13 PHP
javascript prototype,executing,context,closure
2008/12/24 Javascript
动态调用CSS文件的JS代码
2010/07/29 Javascript
使用JavaScript动态设置样式实现代码(2)
2013/01/25 Javascript
jquery的ajaxSubmit()异步上传图片并保存表单数据演示代码
2013/06/04 Javascript
js实现动画特效的文字链接鼠标悬停提示的方法
2015/03/02 Javascript
javascript检查浏览器是否已经启用XX功能
2015/07/10 Javascript
javascript实现信息增删改查的方法
2015/07/25 Javascript
jquery Deferred 快速解决异步回调的问题
2016/04/05 Javascript
用jmSlip编写移动端顶部日历选择控件
2016/10/24 Javascript
angularjs的select使用及默认选中设置
2017/04/08 Javascript
Web开发使用Angular实现用户密码强度判别的方法
2017/09/27 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
Vue动态修改网页标题的方法及遇到问题
2019/06/09 Javascript
jQuery实现轮播图源码
2019/10/23 jQuery
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
浅谈webpack和webpack-cli模块源码分析
2020/01/19 Javascript
Python中使用logging模块打印log日志详解
2015/04/05 Python
python+selenium打印当前页面的titl和url方法
2018/06/22 Python
python利用pandas将excel文件转换为txt文件的方法
2018/10/23 Python
10 行Python 代码实现 AI 目标检测技术【推荐】
2019/06/14 Python
通过 Django Pagination 实现简单分页功能
2019/11/11 Python
详解Python3 中的字符串格式化语法
2020/01/15 Python
python打开文件的方式有哪些
2020/06/29 Python
利用简洁的图片预加载组件提升html5移动页面的用户体验
2016/03/11 HTML / CSS
英国标志性奢侈品牌:Burberry
2016/07/28 全球购物
Smallable意大利家庭概念店:设计师童装及家居装饰
2018/01/08 全球购物
独特的礼品和创新的科技产品:The Grommet
2018/02/24 全球购物
如何查看在weblogic中已经发布的EJB
2012/06/01 面试题
银行委托书范本
2014/04/04 职场文书
个人自荐书范文
2015/03/09 职场文书
远程教育培训心得体会
2016/01/09 职场文书
vue完美实现el-table列宽自适应
2021/05/08 Vue.js
Vue-Element-Admin集成自己的接口实现登录跳转
2021/06/23 Vue.js
苹果可能正在打击不进行更新的 App
2022/04/24 数码科技