详解多线程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提取内容关键词的方法
Mar 16 Python
使用python检测主机存活端口及检查存活主机
Oct 12 Python
Python如何判断数独是否合法
Sep 08 Python
详解Python中for循环是如何工作的
Jun 30 Python
Python中Scrapy爬虫图片处理详解
Nov 29 Python
python3调用百度翻译API实现实时翻译
Aug 16 Python
Python使用reportlab模块生成PDF格式的文档
Mar 11 Python
Python数据类型之String字符串实例详解
May 08 Python
利用pandas合并多个excel的方法示例
Oct 10 Python
pyftplib中文乱码问题解决方案
Jan 11 Python
Python基于QQ邮箱实现SSL发送
Apr 26 Python
python mysql自增字段AUTO_INCREMENT值的修改方式
May 18 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
如何修改和添加Apache的默认站点目录
2013/07/05 PHP
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
jquery+php实现导出datatables插件数据到excel的方法
2015/07/06 PHP
php获取用户真实IP和防刷机制的实例代码
2018/11/28 PHP
Code:findPosX 和 findPosY
2006/12/20 Javascript
发布BlueShow v1.0 图片浏览器(类似lightbox)blueshow.js 打包下载
2007/07/21 Javascript
jquery 子窗口操作父窗口的代码
2009/09/21 Javascript
js获取网页高度(详细整理)
2012/12/28 Javascript
Extjs 4.x 得到form CheckBox 复选框的值
2014/05/04 Javascript
使用Meteor配合Node.js编写实时聊天应用的范例
2015/06/23 Javascript
JS、jQuery中select的用法详解
2016/04/21 Javascript
Document.body.scrollTop的值总为零的快速解决办法
2016/06/09 Javascript
如何理解Vue的.sync修饰符的使用
2017/08/17 Javascript
JavaScript使用递归和循环实现阶乘的实例代码
2018/08/28 Javascript
vue实现重置表单信息为空的方法
2018/09/29 Javascript
详解Express笔记之动态渲染HTML(新手入坑)
2018/12/13 Javascript
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
2019/01/23 Javascript
javascript中的数据类型检测方法详解
2019/08/07 Javascript
js中实现继承的五种方法
2021/01/25 Javascript
[01:52]2020年DOTA2 TI10夏季活动预告片
2020/07/15 DOTA
剖析Python的Twisted框架的核心特性
2016/05/25 Python
python获取时间及时间格式转换问题实例代码详解
2018/12/06 Python
python 非线性规划方式(scipy.optimize.minimize)
2020/02/11 Python
Django自定义全局403、404、500错误页面的示例代码
2020/03/08 Python
使用jupyter notebook将文件保存为Markdown,HTML等文件格式
2020/04/14 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
2020/06/02 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
2020/11/26 Python
Canvas globalCompositeOperation
2018/12/18 HTML / CSS
英国最大的电子零件及配件零售商:Partmaster
2017/04/24 全球购物
法国在线宠物店:zooplus.fr
2018/02/23 全球购物
惊艳的手工时装首饰:Migonne Gavigan
2018/02/23 全球购物
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
2013/07/06 面试题
《大江保卫战》教学反思
2014/04/11 职场文书
《有趣的发现》教学反思
2014/04/15 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang