django 数据库连接模块解析及简单长连接改造方法


Posted in Python onAugust 29, 2019

工作中纯服务端的项目用到了线程池和django的ORM部分。django 的数据库连接在每一个线程中开启一份,并在查询完毕后自动关闭连接。

线程池处理任务时,正常使用的连接中不会被关闭,但由于数据库端有最长连接时间的限制(默认为8小时),在超时后会发生InterfaceError: (0, '')(连接关闭后使用连接/游标)或Error(2006, 'MySQL server has gone away')(mysql 服务器主动关闭连接)这类错误,所以一般会在每个任务线程中调用django.db.connection.close()进行关闭操作。

但对于频繁进行数据库连接并操作数据库的业务,反复创建连接并不是好的选择,这种场景下可以考虑将连接改造为长连接。

1. django 代码的阅读笔记

django.db.__init__.py 
#对象:
connections = ConnectionHandler()
connection = DefaultConnectionProxy()
# 函数
# 重置查询记录缓存
def reset_queries(**kwargs):
 pass
# 关闭不可用或超时(如果有设置 CONN_MAX_AGE)连接
def close_old_connections(**kwargs):
 pass
# 信号
# 在请求开始或完成时自动调用相应处理函数
signals.request_started.connect(reset_queries)
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

重点是connections和connection两个实例

connections 是 ConnectionHandler类

connections.all()会给出一个列表,里面的元素为DatabaseWrapper类

ConnectionHandler内置对象及连接管理:

def __init__():
 self._connections = local()

# 连接包装类里的连接是根据配置情况使用相应的连接
def __getitem__(self, alias):
 '''略'''
 db = self.databases[alias]
 backend = load_backend(db['ENGINE'])
 conn = backend.DatabaseWrapper(db, alias)
 setattr(self._connections, alias, conn)

# 返回所管理的数据库连接
# 管理方式:分数据库,线程管理连接 
def all(self):
 return [self[alias] for alias in self]

# 关闭所有数据库连接
def close_all(self):
 for alias in self:
  try:
   connection = getattr(self._connections, alias)
  except AttributeError:
   continue
  connection.close()

threading.local 是一个全局变量,local的属性是非线程共享的,也就是在每一个线程中都会有单独一个数据库连接实例创建,因为代理及包装的原因,该连接实例为对应backend里的连接(比如,pymysql.connections.Connection)。

在线程池的情况下,close_old_connections方法是不能将线程中的数据库连接关闭的。

connection是DefaultConnectionProxy类的实例,实际是DatabaseWrapper的实例 
(使用了pymysql库:import pymysql; pymysql.install_as_MySQLdb) 
DefaultConnectionProxy?>DatabaseWrapper?>pymysql.connections.Connection(根据connections的处理调用相应的数据库连接包) 
connection有几个关键方法和属性

connection.connection = '被包装的pymysql.connections.Connection实例`
connection.close_at = None if max_age is None else time.time() + max_age # 设置的连接关闭时间

connection.connect()# 获取连接
connection.cursor() # 获取游标
connection.close()# 关闭连接

2. 将数据库连接改造为长连接

max_age(CONN_MAX_AGE) 是可以在settings里面配置的。

由于多个服务共用一套配置, 所以考虑直接在程序里修改

全局变量

max_age = 7 * 3600

在线程内开始时做下判断:

if not db.connection.connection or db.connection.close_at < time.time():
 db.connection.close()
 db.connection.connect()
 db.connection.close_at = time.time() + max_age
 print "A new conn creates !"
else:
 print "Still old conn!"

这样每个线程池中的线程会循环执行任务并只使用同一个连接,并可以控制在自己需要的连接时长后更换连接。

针对线程池的情况,close_old_connections基本没啥用处, 可以跳过该处理

django.db.close_old_connections = lambda **kwargs : None

以上这篇django 数据库连接模块解析及简单长连接改造方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中实现远程调用(RPC、RMI)简单例子
Apr 28 Python
Python程序设计入门(3)数组的使用
Jun 16 Python
python开发之函数定义实例分析
Nov 12 Python
Python中断言Assertion的一些改进方案
Oct 27 Python
Python基于贪心算法解决背包问题示例
Nov 27 Python
Python2 Selenium元素定位的实现(8种)
Feb 25 Python
Python3几个常见问题的处理方法
Feb 26 Python
Django的性能优化实现解析
Jul 30 Python
Python实现链表反转的方法分析【迭代法与递归法】
Feb 22 Python
Django框架models使用group by详解
Mar 11 Python
使用OpenCV对车道进行实时检测的实现示例代码
Jun 19 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 Python
解决Django连接db遇到的问题
Aug 29 #Python
Python pandas实现excel工作表合并功能详解
Aug 29 #Python
python openCV获取人脸部分并存储功能
Aug 28 #Python
python lambda表达式在sort函数中的使用详解
Aug 28 #Python
python实现微信小程序用户登录、模板推送
Aug 28 #Python
使用Python脚本zabbix自定义key监控oracle连接状态
Aug 28 #Python
django删除表重建的实现方法
Aug 28 #Python
You might like
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页
2006/10/09 PHP
谈谈PHP的输入输出流
2007/02/14 PHP
Zend Framework教程之Resource Autoloading用法实例
2016/03/08 PHP
PHP判断一个数组是另一个数组子集的方法详解
2017/07/31 PHP
PHP自动生成缩略图函数的源码示例
2019/03/18 PHP
PHP微信网页授权的配置文件操作分析
2019/05/29 PHP
php和nginx交互实例讲解
2019/09/24 PHP
setInterval 和 setTimeout会产生内存溢出
2008/02/15 Javascript
js中的值类型和引用类型小结 文字说明与实例
2010/12/12 Javascript
javascrip客户端验证文件大小及文件类型并重置上传
2011/01/12 Javascript
深入理解JavaScript系列(9) 根本没有“JSON对象”这回事!
2012/01/15 Javascript
jQuery div层的放大与缩小简单实现代码
2013/03/28 Javascript
jquery遍历筛选数组的几种方法和遍历解析json对象
2013/12/13 Javascript
JS面向对象编程详解
2016/03/06 Javascript
AngularJS中的过滤器filter用法完全解析
2016/04/22 Javascript
JS正则RegExp.test()使用注意事项(不具有重复性)
2016/12/28 Javascript
详细介绍RxJS在Angular中的应用
2017/09/23 Javascript
Array数组对象中的forEach、map、filter及reduce详析
2018/08/02 Javascript
vue组件化中slot的基本使用方法
2019/05/01 Javascript
Python中获取网页状态码的两个方法
2014/11/03 Python
CentOS安装pillow报错的解决方法
2016/01/27 Python
Python对数据库操作
2016/03/28 Python
用Python解决计数原理问题的方法
2016/08/04 Python
Python中index()和seek()的用法(详解)
2017/04/27 Python
基于python指定包的安装路径方法
2018/10/27 Python
对python实现模板生成脚本的方法详解
2019/01/30 Python
Pyorch之numpy与torch之间相互转换方式
2019/12/31 Python
基于python3抓取pinpoint应用信息入库
2020/01/08 Python
总监职责范文
2013/11/09 职场文书
企业节能减排实施方案
2014/03/19 职场文书
《蜗牛的奖杯》教后反思
2014/04/24 职场文书
2014教师党员自我评议(5篇)
2014/09/20 职场文书
篮球友谊赛通讯稿
2014/10/10 职场文书
关于感谢信的范文
2015/01/23 职场文书
2015国庆节感想
2015/08/04 职场文书
工作自我评价范文
2019/03/21 职场文书