详解多线程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字符串处理实现单词反转
Jun 14 Python
Python 多线程的实例详解
Sep 07 Python
python 读写中文json的实例详解
Oct 29 Python
Python有序查找算法之二分法实例分析
Dec 11 Python
windows环境下tensorflow安装过程详解
Mar 30 Python
python3+PyQt5使用数据库窗口视图
Apr 24 Python
python实现textrank关键词提取
Jun 22 Python
利用python将图片版PDF转文字版PDF
May 03 Python
python判断一个对象是否可迭代的例子
Jul 22 Python
python中return不返回值的问题解析
Jul 22 Python
python读取excel数据并且画图的实现示例
Feb 08 Python
python 下载文件的几种方式分享
Apr 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
桌面中心(二)数据库写入
2006/10/09 PHP
PHP中对缓冲区的控制实现代码
2013/09/29 PHP
PHP经典算法集锦【经典收藏】
2016/09/14 PHP
jquery不支持toggle()高(新)版本的问题解决
2016/09/24 PHP
php 猴子摘桃的算法
2017/06/20 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
php+ajax实现仿百度查询下拉内容功能示例
2017/10/20 PHP
JavaScript的面向对象(一)
2006/11/09 Javascript
js form action动态修改方法
2008/11/04 Javascript
lyhucSelect基于Jquery的Select数据联动插件
2011/03/29 Javascript
js解析与序列化json数据(一)json.stringify()的基本用法
2013/02/01 Javascript
手机平板等移动端适配跳转URL的js代码
2014/01/25 Javascript
使用bootstrap3开发响应式网站
2016/05/12 Javascript
jquery把int类型转换成字符串类型的方法
2016/10/07 Javascript
ES6中字符串string常用的新增方法小结
2017/11/07 Javascript
Node.js中的不安全跳转如何防御详解
2018/10/21 Javascript
详解微信小程序自定义组件的实现及数据交互
2019/07/22 Javascript
vue实现页面滚动到底部刷新
2019/08/16 Javascript
Vue Render函数创建DOM节点代码实例
2020/07/08 Javascript
原生JavaScript实现拖动校验功能
2020/09/29 Javascript
Python通过OpenCV的findContours获取轮廓并切割实例
2018/01/05 Python
Python标准库使用OrderedDict类的实例讲解
2019/02/14 Python
详解python 降级到3.6终极解决方案
2020/02/06 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
python实现学生信息管理系统(精简版)
2020/11/27 Python
Django 用户认证Auth组件的使用
2020/11/30 Python
前台文员岗位职责
2013/12/28 职场文书
数控专业大学毕业生职业规划范文
2014/02/06 职场文书
《小石潭记》教学反思
2014/02/13 职场文书
《中彩那天》教学反思
2014/02/22 职场文书
2015大学自主招生自荐信范文
2015/03/04 职场文书
新郎婚礼致辞
2015/07/27 职场文书
2016年小学生清明节广播稿
2015/12/17 职场文书
CSS filter 有什么神奇用途
2021/05/25 HTML / CSS
高性能跳频抗干扰宽带自组网电台
2022/02/18 无线电
最新最全的手机号验证正则表达式
2022/02/24 Javascript