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解决字典中的值是列表问题的方法
Mar 04 Python
python发送邮件的实例代码(支持html、图片、附件)
Mar 04 Python
python从入门到精通(DAY 1)
Dec 20 Python
Python中xrange与yield的用法实例分析
Dec 26 Python
解决Python pandas df 写入excel 出现的问题
Jul 04 Python
解决pycharm回车之后不能换行或不能缩进的问题
Jan 16 Python
python DataFrame 取差集实例
Jan 30 Python
python实现连续变量最优分箱详解--CART算法
Nov 22 Python
TensorFlow学习之分布式的TensorFlow运行环境
Feb 05 Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 Python
Python实战之实现简易的学生选课系统
May 25 Python
Python利用zhdate模块实现农历日期处理
Mar 31 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函数
2008/10/03 PHP
PHP手机号码归属地查询代码(API接口/mysql)
2012/09/04 PHP
PHP执行批量mysql语句的解决方法
2013/05/02 PHP
CI框架扩展系统核心类的方法分析
2016/05/23 PHP
基于jquery的高性能td和input切换并可修改内容实现代码
2011/01/09 Javascript
判断用户是否在线的代码
2011/03/05 Javascript
javascript中IE浏览器不支持NEW DATE()带参数的解决方法
2012/03/01 Javascript
jQuery实现html元素拖拽
2015/07/21 Javascript
bootstrap表格分页实例讲解
2016/12/30 Javascript
Node.js 基础教程之全局对象
2017/08/06 Javascript
使用vue-resource进行数据交互的实例
2017/09/02 Javascript
Vue Element使用icon图标教程详解(第三方)
2018/02/07 Javascript
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
JS控制下拉列表左右选择实例代码
2020/05/08 Javascript
如何在postman中添加cookie信息步骤解析
2020/06/30 Javascript
[45:16]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第一场 12.12
2020/12/16 DOTA
Python网络爬虫中的同步与异步示例详解
2018/02/03 Python
python 阶乘累加和的实例
2019/02/01 Python
Django发送邮件功能实例详解
2019/09/02 Python
Python 中 -m 的典型用法、原理解析与发展演变
2019/11/11 Python
Python requests模块安装及使用教程图解
2020/06/30 Python
Python return语句如何实现结果返回调用
2020/10/15 Python
CSS实现限制字数功能当对象内文本溢出时显示省略标记
2014/08/20 HTML / CSS
CSS3的resize属性使用初探
2015/09/27 HTML / CSS
HTML5中canvas中的beginPath()和closePath()的重要性
2018/08/24 HTML / CSS
Linux开机引导的步骤是什么
2015/10/19 面试题
法律专业个人实习自我鉴定
2013/09/23 职场文书
心碎乌托邦的创业计划书范文
2013/12/26 职场文书
物流专业求职计划书
2014/01/10 职场文书
竞聘演讲稿开场白
2014/08/25 职场文书
园艺专业毕业生求职信
2014/09/02 职场文书
单身申明具结书
2015/02/26 职场文书
你离财务总监还有多远?速览CFO的岗位职责
2019/11/18 职场文书
JS一分钟在github+Jekyll的博客中添加访问量功能的实现
2021/04/03 Javascript
纯CSS实现酷炫的霓虹灯效果
2021/04/13 HTML / CSS
利用Matlab绘制各类特殊图形的实例代码
2021/07/16 Python