详解多线程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安装第三方库的3种方法
Jun 21 Python
python利用thrift服务读取hbase数据的方法
Dec 27 Python
对python读取zip压缩文件里面的csv数据实例详解
Feb 08 Python
Python选择网卡发包及接收数据包
Apr 04 Python
Python实现多态、协议和鸭子类型的代码详解
May 05 Python
使用pyecharts生成Echarts网页的实例
Aug 12 Python
python实现统计代码行数的小工具
Sep 19 Python
python使用PIL剪切和拼接图片
Mar 23 Python
pytorch 查看cuda 版本方式
Jun 23 Python
Python使用paramiko连接远程服务器执行Shell命令的实现
Mar 04 Python
Python中re模块的元字符使用小结
Apr 07 Python
PYTHON基于Pyecharts绘制常见的直角坐标系图表
Apr 28 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 实例化类的一点摘记
2008/03/23 PHP
PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
2012/06/17 PHP
php抽象类使用要点与注意事项分析
2015/02/09 PHP
PHP程序中的文件锁、互斥锁、读写锁使用技巧解析
2016/03/21 PHP
ThinkPHP3.2框架操作Redis的方法分析
2019/05/05 PHP
php设计模式之策略模式应用案例详解
2019/06/17 PHP
js的alert弹出框出现乱码解决方案
2013/09/02 Javascript
js控制表单不能输入空格的小例子
2013/11/20 Javascript
javascript:void(0)点击登录没反应怎么解决
2015/11/13 Javascript
Node.js编写爬虫的基本思路及抓取百度图片的实例分享
2016/03/12 Javascript
EasyUI框架 使用Ajax提交注册信息的实现代码
2017/09/27 Javascript
JavaScript canvas实现围绕旋转动画
2017/11/18 Javascript
基于node.js实现微信支付退款功能
2017/12/19 Javascript
vue使用iframe嵌入网页的示例代码
2020/06/09 Javascript
vue移动端的左右滑动事件详解
2020/06/17 Javascript
python代码检查工具pylint 让你的python更规范
2012/09/05 Python
解析Python中的二进制位运算符
2015/05/13 Python
Python下载懒人图库JavaScript特效
2015/05/28 Python
Python PyQt5标准对话框用法示例
2017/08/23 Python
python隐藏终端执行cmd命令的方法
2019/06/24 Python
利用ImageAI库只需几行python代码实现目标检测
2019/08/09 Python
python 检查数据中是否有缺失值,删除缺失值的方式
2019/12/02 Python
python几种常用功能实现代码实例
2019/12/25 Python
Python实现自动签到脚本功能
2020/08/20 Python
python如何对链表操作
2020/10/10 Python
服装设计专业毕业生推荐信
2013/11/09 职场文书
成龙霸王洗发水广告词
2014/03/14 职场文书
经典广告词大全
2014/03/14 职场文书
师范生求职信
2014/06/14 职场文书
师德师风自我剖析材料
2014/09/27 职场文书
给校长的建议书作文400字
2015/09/14 职场文书
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang
java实现对Hadoop的操作
2021/07/01 Java/Android
从QQtabBar看css命名规范BEM的详细介绍
2021/08/07 HTML / CSS
Java SSM配置文件案例详解
2021/08/30 Java/Android
PostGIS的安装与入门使用指南
2022/01/18 PostgreSQL