详解多线程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 相关文章推荐
如何搜索查找并解决Django相关的问题
Jun 30 Python
Python生成随机数组的方法小结
Apr 15 Python
python 简单的绘图工具turtle使用详解
Jun 21 Python
Python实现识别手写数字大纲
Jan 29 Python
多个应用共存的Django配置方法
May 30 Python
Python数据预处理之数据规范化(归一化)示例
Jan 08 Python
Python中字符串String的基本内置函数与过滤字符模块函数的基本用法
May 27 Python
python字符串中匹配数字的正则表达式
Jul 03 Python
django中使用POST方法获取POST数据
Aug 20 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
Oct 14 Python
pytorch 实现张量tensor,图片,CPU,GPU,数组等的转换
Jan 13 Python
解决python使用list()时总是报错的问题
May 05 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
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
深入PHP中慎用双等于(==)的详解
2013/06/06 PHP
php中文验证码实现示例分享
2014/01/12 PHP
PHP中list方法用法示例
2016/12/01 PHP
php输出控制函数和输出函数生成静态页面
2019/06/27 PHP
laravel解决迁移文件一次删除创建字段报错的问题
2019/10/24 PHP
jquery 必填项判断表单是否为空的方法
2008/09/14 Javascript
js监听键盘事件示例代码
2013/07/26 Javascript
js获取光标位置和设置文本框光标位置示例代码
2014/01/09 Javascript
node.js中的定时器nextTick()和setImmediate()区别分析
2014/11/26 Javascript
JavaScript中的数学运算介绍
2014/12/29 Javascript
jQuery弹出框代码封装DialogHelper
2015/01/30 Javascript
JQuery ztree带筛选、异步加载实例讲解
2016/02/25 Javascript
JS实现改变HTML上文字颜色和内容的方法
2016/12/30 Javascript
bootstrapValidator.min.js表单验证插件
2017/02/09 Javascript
Vue自定义指令使用方法详解
2017/08/21 Javascript
js 显示日期时间的实例(时间过一秒加1)
2017/10/25 Javascript
微信小程序自定义toast实现方法详解【附demo源码下载】
2017/11/28 Javascript
自定义vue组件发布到npm的方法
2018/05/09 Javascript
require.js 加载过程与使用方法介绍
2018/10/30 Javascript
解决element ui select下拉框不回显数据问题的解决
2019/02/20 Javascript
JavaScript Array对象基本方法详解
2019/09/03 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
以911新闻为例演示Python实现数据可视化的教程
2015/04/23 Python
各个系统下的Python解释器相关安装方法
2015/10/12 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
详解python里使用正则表达式的全匹配功能
2017/10/19 Python
python多线程调用exit无法退出的解决方法
2019/02/18 Python
Python中import导入不同目录的模块方法详解
2020/02/18 Python
Toppik顶丰增发纤维官网:解决头发稀疏
2017/12/30 全球购物
优秀党员主要事迹
2014/01/19 职场文书
电焊工工作岗位职责
2014/02/06 职场文书
竞聘书怎么写,如何写?
2014/03/31 职场文书
党员学习中共十八大报告思想汇报
2014/09/15 职场文书
评估“风险”创业计划的几大要点
2019/08/12 职场文书
《进击的巨人》新联动CM 兵长强势出击兽巨人
2022/04/05 日漫