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函数可变参数定义及其参数传递方式实例详解
May 25 Python
python显示生日是星期几的方法
May 27 Python
在Linux系统上安装Python的Scrapy框架的教程
Jun 11 Python
Python爬虫框架Scrapy实战之批量抓取招聘信息
Aug 07 Python
实例Python处理XML文件的方法
Aug 31 Python
Python聊天室程序(基础版)
Apr 01 Python
pandas string转dataframe的方法
Apr 11 Python
浅析python中的迭代与迭代对象
Oct 08 Python
python爬虫模拟浏览器的两种方法实例分析
Dec 09 Python
Python3.x+迅雷x 自动下载高分电影的实现方法
Jan 12 Python
Django --Xadmin 判断登录者身份实例
Jul 03 Python
Python如何读写二进制数组数据
Aug 01 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实现的获取网页中的图片并保存到本地的代码
2010/01/05 PHP
PHP获取文件相对路径的方法
2015/02/26 PHP
详细解读PHP的Yii框架中登陆功能的实现
2015/08/21 PHP
PHP类的声明与实例化及构造方法与析构方法详解
2016/01/26 PHP
PHP基本语法实例总结
2016/09/09 PHP
CI框架表单验证实例详解
2016/11/21 PHP
Laravel中encrypt和decrypt的实现方法
2017/09/24 PHP
jQuery功能函数详解
2015/02/01 Javascript
Windows下用PyCharm和Visual Studio开始Python编程
2015/10/26 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
详解JavaScript for循环中发送AJAX请求问题
2020/06/23 Javascript
基于node实现websocket协议
2016/04/25 Javascript
JavaScript中原型链存在的问题解析
2016/09/25 Javascript
vue2.0使用Sortable.js实现的拖拽功能示例
2017/02/21 Javascript
JS字符串false转boolean的方法(推荐)
2017/03/08 Javascript
详解AngularJS 模块化
2017/06/14 Javascript
5分钟打造简易高效的webpack常用配置
2017/07/04 Javascript
Vue keep-alive实践总结(推荐)
2017/08/31 Javascript
vue初始化动画加载的实例
2018/09/01 Javascript
浅谈webpack4 图片处理汇总
2018/09/12 Javascript
js+html5 canvas实现ps钢笔抠图
2019/04/28 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
Array.filter中如何正确使用Async
2020/11/04 Javascript
vue的$http的get请求要加上params操作
2020/11/12 Javascript
Python编程scoketServer实现多线程同步实例代码
2018/01/29 Python
使用python编写监听端
2018/04/12 Python
Scrapy框架爬取Boss直聘网Python职位信息的源码
2019/02/22 Python
python Gunicorn服务器使用方法详解
2019/07/22 Python
python语言线程标准库threading.local解读总结
2019/11/10 Python
解决python3插入mysql时内容带有引号的问题
2020/03/02 Python
文秘专业自荐信
2013/10/14 职场文书
祖国在我心中演讲稿450字
2014/09/05 职场文书
2014年乡镇工作总结
2014/11/21 职场文书
英语教师个人总结
2015/02/09 职场文书
初中班主任心得体会
2016/01/07 职场文书
详解Html5项目适配系统深色模式方案总结
2021/04/14 HTML / CSS