详解多线程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制作检测Linux运行信息的工具的教程
Apr 01 Python
在Gnumeric下使用Python脚本操作表格的教程
Apr 14 Python
在Python的Flask框架中验证注册用户的Email的方法
Sep 02 Python
Python 列表(List) 的三种遍历方法实例 详解
Apr 15 Python
分享一个简单的python读写文件脚本
Nov 25 Python
Python中一些不为人知的基础技巧总结
May 19 Python
浅析Python数字类型和字符串类型的内置方法
Dec 22 Python
python GUI库图形界面开发之PyQt5拖放控件实例详解
Feb 25 Python
Android Q之气泡弹窗的实现示例
Jun 23 Python
基于Python爬取股票数据过程详解
Oct 21 Python
python 使用cycle构造无限循环迭代器
Dec 02 Python
详解Python+OpenCV绘制灰度直方图
Mar 22 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
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
PHP实现多进程并行操作的详解(可做守护进程)
2013/06/18 PHP
php实现数据库的增删改查
2017/02/26 PHP
PHP pthreads v3下同步处理synchronized用法示例
2020/02/21 PHP
window.location.hash 属性使用说明
2010/03/20 Javascript
jquery实现手机发送验证码的倒计时代码
2014/02/12 Javascript
JavaScript检测字符串中是否含有html标签实现方法
2015/07/01 Javascript
JavaScript判断变量是否为数组的方法(Array)
2016/02/24 Javascript
值得分享和收藏的Bootstrap学习教程
2016/05/12 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
HTML的select控件美化
2017/03/27 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
2017/05/24 Javascript
Vue学习笔记进阶篇之函数化组件解析
2017/07/21 Javascript
BACKBONE.JS 简单入门范例
2017/10/17 Javascript
在vue中实现简单页面逆传值的方法
2017/11/27 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
2018/04/23 Javascript
小程序实现分类页
2019/07/12 Javascript
如何使用RoughViz可视化Vue.js中的草绘图表
2021/01/30 Vue.js
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
基于Python实现的百度贴吧网络爬虫实例
2015/04/17 Python
Windows下PyMongo下载及安装教程
2015/04/27 Python
详细讲解Python中的文件I/O操作
2015/05/24 Python
在Django的模板中使用认证数据的方法
2015/07/23 Python
Flask框架的学习指南之开发环境搭建
2016/11/20 Python
Numpy数组转置的两种实现方法
2018/04/17 Python
Mixbook加拿大:照片书,照片卡,剪贴簿,年历和日历
2017/02/21 全球购物
英国领先的在线药房:Pharmacy First
2017/09/10 全球购物
英国家居用品和家居装饰品购物网站:Cox & Cox
2019/08/25 全球购物
什么是索引指示器
2012/08/20 面试题
模特职业生涯规划范文
2014/02/26 职场文书
低碳环保倡议书
2014/04/14 职场文书
幼儿园教师的考核评语
2014/04/18 职场文书
十周年庆典策划方案
2014/06/03 职场文书
MySQL中distinct与group by之间的性能进行比较
2021/05/26 MySQL
Java 超详细讲解IO操作字节流与字符流
2022/03/25 Java/Android
Python测试框架pytest核心库pluggy详解
2022/08/05 Golang