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处理python编码问题
Mar 13 Python
给Python初学者的一些编程技巧
Apr 03 Python
Python实现删除列表中满足一定条件的元素示例
Jun 12 Python
python使用fork实现守护进程的方法
Nov 16 Python
使用Python OpenCV为CNN增加图像样本的实现
Jun 10 Python
Python 类,property属性(简化属性的操作),@property,property()用法示例
Oct 12 Python
Flask项目中实现短信验证码和邮箱验证码功能
Dec 05 Python
python 解决cv2绘制中文乱码问题
Dec 23 Python
Python基于stuck实现scoket文件传输
Apr 02 Python
Python+OpenCV图像处理——实现轮廓发现
Oct 23 Python
Python 调用 ES、Solr、Phoenix的示例代码
Nov 23 Python
python之基数排序的实现
Jul 26 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
Php+SqlServer实现分页显示
2006/10/09 PHP
tp5.1 框架查询表达式用法详解
2020/05/25 PHP
基于逻辑运算的简单权限系统(实现) JS 版
2007/03/24 Javascript
jQuery 使用手册(七)
2009/09/23 Javascript
推荐40个非常优秀的jQuery插件和教程【系列三】
2011/11/09 Javascript
JavaScript中的this关键字介绍与使用实例
2013/06/21 Javascript
Javascript动态引用CSS文件的2种方法介绍
2014/06/06 Javascript
jquery遍历函数siblings()用法实例
2015/12/24 Javascript
jquery 将当前时间转换成yyyymmdd格式的实现方法
2016/06/01 Javascript
JS简单实现tab切换效果的多窗口显示功能
2016/09/07 Javascript
javascript使用递归算法求两个数字组合功能示例
2017/01/03 Javascript
JavaScript简单拖拽效果(1)
2017/05/17 Javascript
谈谈VUE种methods watch和compute的区别和联系
2017/08/01 Javascript
React学习笔记之列表渲染示例详解
2017/08/22 Javascript
详解微信UnionID作用
2019/05/15 Javascript
使用微信SDK自定义分享的方法
2019/07/03 Javascript
如何在wxml中直接写js代码(wxs)
2019/11/14 Javascript
go语言计算两个时间的时间差方法
2015/03/13 Python
使用Python标准库中的wave模块绘制乐谱的简单教程
2015/03/30 Python
python类中super()和__init__()的区别
2016/10/18 Python
python 根据正则表达式提取指定的内容实例详解
2016/12/04 Python
python2.6.6如何升级到python2.7.14
2018/04/08 Python
python框架flask表单实现详解
2019/11/04 Python
DataFrame.to_excel多次写入不同Sheet的实例
2019/12/02 Python
TensorFlow学习之分布式的TensorFlow运行环境
2020/02/05 Python
解决Django Haystack全文检索为空的问题
2020/05/19 Python
浅谈Keras的Sequential与PyTorch的Sequential的区别
2020/06/17 Python
html5本地存储_动力节点Java学院整理
2017/07/12 HTML / CSS
印度在线购买电子产品网站:Croma
2020/01/02 全球购物
技校生自我鉴定
2013/12/08 职场文书
小学毕业感言150字
2014/02/05 职场文书
优秀教师感人事迹材料
2014/05/04 职场文书
社区个人对照检查材料(群众路线)
2014/09/26 职场文书
关于远足的感想
2015/08/10 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers