DBUtil内部实现过程解读
python数据库连接工具DBUtils
模块
DBUtils套件包含两个模块子集,一个适用于兼容DB-API 2接口的模块,一个适用于PyGreSQL的模块。
- Universal DB-API 2 variant
该子集下的模块依赖关系如图:
- Classic PyGreSQL variant
该子集下的模块依赖关系如图:
SimplePooledDB
DBUtils.SimplePooledDB
是池化数据库连接中非常基础的一种实现。相较于PooledDB
,它并不那么复杂,且缺少failover机制。SimplePooledDB应视为一种概念演示,不要直接在生产环境使用。
SteadyDB
DBUtils.SteadyDB
基于兼容DB-API 2接口的数据库模块创建的普通连接,实现了"加强"连接。具体指当数据库连接关闭、丢失或使用频率超出限制时,将自动重新获取连接。
典型的应用场景如下:在某个维持了某些数据库连接的程序运行时重启了数据库,或在某个防火墙隔离的网络中访问远程数据库时重启了防火墙。
PersistentDB
DBUtils.PersistentDB
实现了稳定,线程仿射(thread-affine
),持久化的数据库连接。下图显式了使用PersistentDB进行连接时涉及的连接层:
某个线程第一次开启一个数据库连接时,该连接将用于此特定线程。即使在线程中关闭连接,连接也会保持打开状态,以便同一个线程的下一次连接请求直接使用。线程结束时该连接会自动关闭。
简而言之:PersistentDB会回收数据库连接从而在整体上增加多线程应用的数据库访问性能,它确保线程之间永远不会共享连接。
因此即使底层的DB-API模块不是connection级别的线程安全,PersistentDB也可以完美实现线程安全,避免在其他线程更改数据库会话或执行跨多个SQL指令的事务时出现问题。
要使用PersistentDB模块,首先传递以下参数创建PersistentDB实例:
- creator:兼容DB-API 2的数据库模块或返回DB-API 2连接的任意函数
- maxusage:单个连接的最大重用次数(0或None表示无重用次数限制),达到该限制后自动关闭并重新打开连接
- setsession:设置连接会话的sql指令列表,比如["set wait_timeout = 100", ...]
- failures:异常类或异常类元组。在默认的
(OperationalError, InternalError)
不能处理连接failover机制时使用 - ping:如果
ping()
方法可用,该值表示何时使用ping()方法检查连接(0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always, and all other bit combinations of these values
) - closeable:如果设置为True,将允许手动close()连接,默认为False,忽略关闭连接的操作,只在线程终止时自动关闭
- threadlocal:表示thread-local数据的类。设置值为
threading.local
可能获取连接的速度更快,但不一定适用于所有情况(例如,mod_wsgi
会清空requests之间的threading.local数据) - 传递给creator参数值创建connection对象的参数,如host, database等
import pymysql
from DBUtils.PersistentDB import PersistentDB
persist = PersistentDB(creator=pymysql, user="root", passwd="123456", db="test")
# conn的使用和常规DB-API 2接口类似
conn = persist.connection()
NOTE:需要在连接上调用begin()
方法明确开启事务。这可以确保a.只在事务完成时才重新打开连接b.连接被同一个线程重用时回滚。
PooledDB
DBUtils.PooledDB
实现了稳定、线程安全的缓存连接池。下图显式了使用PooledDB进行连接时涉及的连接层:
使用正整数的maxshared
参数和connection级别的线程安全的creator
参数创建连接池时,连接池中的连接默认是线程间共享的。但仍可以请求非线程共享的专用数据库连接。
除了共享连接池外,还可以创建至少mincached
个,至多maxcached
个连接的空闲连接池,在共享连接池未满(不太理解)或线程请求专用数据库连接时使用。当某个线程关闭不再共享的连接时,该连接将回收到空闲连接池以便再次使用。
如果底层的DB-API 2模块非线程安全,将使用线程锁确保PooledDB连接是线程安全的。但对于线程专用的连接,要小心更改数据库会话或执行跨多个SQL指令的事务带来的不良影响。
要使用PoolDB模块,首先传递以下参数创建PoolDB实例:
- creator:同PersistentDB
- mincached:连接池中空闲连接的初始数量(0表示不创建初始空闲连接)
- maxcached:连接池中允许的最大空闲连接数(0或None表示无限制)
- maxshared:允许的最大共享连接数(0或None表示所有连接都是专用的),
When this maximum number is reached, connections are shared if they have been requested as shareable
- maxconnections:允许的最大连接数(0或None表示无限制)
- blocking:查过最大值是否阻塞。True表示将阻塞直到释放新的连接,默认False表示抛出异常
- maxusage:同PersistentDB
- setsession:同PersistentDB
- reset:返回连接池时应该怎样重置连接(False或None将只回滚明确调用了
begin()
开启的事务,默认值为True,出于安全考虑总是会回滚) - failures:同PersistentDB
- ping:同PersistentDB
- 传递给creator参数值创建connection对象的参数,如host, database等
import pymysql
from DBUtils.PooledDB import PooledDB
pool = PooledDB(creator=pymysql, 5, user="root", passwd="123456", db="test")
# conn的使用和常规DB-API 2接口类似
conn = pool.connection()
对于线程共享的连接池,可以用以下方式获取线程专用连接:
conn = pool.connection(shareable=False)
# 或者
conn = pool.dedicated_connection()
对于不再使用的连接,调用close()方法回收到连接池。
在多线程环境中,不要写以下代码,这会导致连接过早释放并被其他线程重用,如果连接非线程安全可能导致程序出现严重错误:
pool.connection().cursor().execute(...)
NOTE:需要在连接上调用begin()
方法明确开启事务。这可以确保a.只在事务完成时才重新打开连接b.连接在返回连接池之前执行回滚c.连接不会被其他线程共享
如何选择
PooledDB和PersistentDB都通过回收数据库连接,且即使数据库连接中断也能保持稳定性的方式从而达到提升数据库访问性能的目的。在现实场景中应该如何选择呢?对于保持常量线程数且频繁使用数据库的应用,使用PersistentDB;对于频繁开启、结束线程的应用,使用PooledDB。
其他
如果程序中使用了ORM框架,如SQLObject
或SQLAlchemy
,不需要使用DBUtils,因为这些框架自身维护了连接池。
数据库线程安全级别:
比如pymysql
就是可以共享模块但不能共享连接,查看方式pymysql.threadsafety
DBUtil内部实现过程解读的更多相关文章
- 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程
[前提] 想要实现使用某种语言,比如Python,C#等,去实现模拟登陆网站的话,首先要做的事情就是使用某种工具,去分析本身使用浏览器去登陆网页的时候,其内部的执行过程,内部逻辑. 此登陆的逻辑过程, ...
- CLRMonitor - 跟踪CLR内部执行过程工具
CLRMonitor v1.0.1511.13 点击此处下载 软件介绍:这款软件主要用于跟踪CLR内部执行过程,定位当前程序执行的命名空间以及方法名等信息.可以迅速找到被跟踪程序的当前执行方法名.本软 ...
- 【Spring-web】RestTemplate源码学习——梳理内部实现过程
2016-12-28 by 安静的下雪天 http://www.cnblogs.com/quiet-snowy-day/p/6228198.html 提示:使用手机浏览时请注意,图多费流量. 本篇 ...
- ORACLE之SQL语句内部解析过程【weber出品】
一.客户端通过监听连接到数据库,数据库开启一个server process进程来接收客户端传过来的sql. 1.这条sql语句从来都没有被执行过.(硬解析) 2.这条sql语句被执行过.(软解析) 二 ...
- STM32启动过程解读与跟踪验证
经过查阅各种官方文献和对代码进行单步跟踪,详细地叙述了STM32加电启动的具体过程.对于关键性的语句都指明了出处.下面将学习成果分享给大家,由于笔者知识有限,不当之处敬请指出. 为了更好的说明问题,先 ...
- HttpApplication 对象的创建过程及HttpModule过滤器的内部实现过程
最近通过Reflector学习了一下asp.net内部的原理,做做笔记,方便以后查阅. 先看下HttpApplication 对象的创建过程 从IHttpHandler applicationInst ...
- 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?
先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...
- Struts2内部执行过程
首先是Struts2的流程图. 一.当有一个请求的时候.执行以下流程. 1 客户端初始化一个指向Servlet容器的请求: 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做Act ...
- mysql系列二、mysql内部执行过程
向MySQL发送一个请求的时候,MySQL到底做了什么 客户端发送一条查询给服务器. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器端进行SQL解析.预 ...
随机推荐
- 更改Ubuntu下默认Python版本
更改Ubuntu下默认Python版本 首先查看系统内有哪些版本的Python ls /usr/bin/python* 查看当前python版本 python --version 基于用户修改默认版本 ...
- RTC — 软件协作开发管理平台
IBM Rational Team Concert (简称RTC )是构建在IBM Rational面向软件交付技术的下一代协作平台Jazz平台上的一个商用产品.一个协作式的软件开发环境,它包含了集成 ...
- vue---子调父 $emit (把子组件的数据传给父组件)
ps:App.vue 父组件 Hello.vue 子组件 ps:App.vue 父组件 Hello.vue 子组件 <!--App.vue :--> <template> & ...
- 前端学习笔记--CSS入门
1.css概述: 2.css语法: 3.css添加方法: 用单独的文件存储css样式的优点: 优先级: h3得到的样式是内嵌样式覆盖了外部样式. 4.css选择器 标签选择器: 类别选择器: ID选择 ...
- python----装饰器(几种常见方式的使用与理解)
更详细的装饰器,真心实力推荐,里面介绍的很清楚,介绍可见链接:https://blog.csdn.net/buster_zr/article/details/81104551 1.装饰器的理论: (1 ...
- 54、servlet3.0-ServletContainerInitializer
54.servlet3.0-ServletContainerInitializer Shared libraries(共享库) / runtimes pluggability(运行时插件能力) 1.S ...
- 最短路--Dijkstra
Dijkstra--单源最短路 算法思想 主要记住这句话:每次选择没有被访问过的,并且dis最小的点,加入集合,更新dis 模板 int dis[maxn],vis[maxn]; //距离,标记 vo ...
- MongoDB 如何保证 oplog 顺序?
MongoDB 复制集里,主备节点间通过 oplog 来同步数据,Priamry 上写入数据时,会记录一条oplog,Secondary 从 Primary 节点拉取 oplog并重放,以保证最终存储 ...
- Elasticsearch 调优之 shrink
对于索引分片数量,我们一般在模板中统一定义,在数据规模比较大的集群中,索引分片数一般也大一些,在我的集群中设置为 24.但是,并不是所有的索引数据量都很大,这些小数据量的索引也同样有较大的分片数.在 ...
- GreenPlum 数据备份与恢复
GreenPlum数据备份与恢复gp_dump是GP并行备份的备份工具,在运行gp_dump的时候master与所有的segment节点都开始备份(standby节点和segment节点中的mirro ...