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解析.预 ...
随机推荐
- 2.Git 结构
1.Git 结构: 使用git add命令将写的代码暂存到暂存区:使用git commit命令将暂存区的代码提交到本地库: 2. Git 结构及其代码托管中心: workSpace:工作区(写代码). ...
- Go语言中的数据格式(json、xml 、msgpack、protobuf)
在分布式的系统中,因为涉及到数据的传输,所以一定会进行数据的交换,此时就要定义数据交换的格式,例如二进制.Json.Xml等等.本篇文章就是总结一下常用的几种数据格式. 一.Json格式 如果想使用J ...
- Stages — 研发过程可视化建模和管理平台
Stages 是德国Method park公司的产品,用于帮助企业定义.管理.发布.控制.优化其研发过程,同时使其研发过程符合CMMI.ASPICE.ISO26262等标准.Stages的核心理念是把 ...
- JavaScript003,用法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 7月新的开始 - Axure学习06 - 母版的使用
母版的使用 主导航.底部.在很多页面上都是一样的: 如果在每一个页面都写一次的化.话.是非常浪费时间的,为了方便.可以使用母版: 母版可以帮助我们将一些元素重复利用,既可以保证页面的统一性.还可以节省 ...
- celery timeout的拦截
0X01 场景 celery任务超时报错,想查看是传入哪一类数据运行时导致的超时(哪一个插件),但是该报错难以拦截. [2019-06-30 17:23:21,070: ERROR/MainProce ...
- php MySQL 数据类型
MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 数值类型 MySQL支持所有标准S ...
- Neo4j 在Linux下的安装登录
第一步:安装JDK https://blog.csdn.net/qq_33951308/article/details/82933535 第二步:下载并安装neo4j 下载地址 或者直接用wget ...
- nginx + keepalived双活配置
一.安装nginx 我们这边默认安装的nginx的是1.12.2的版本,所以我们需要安装1.16.1版本的nginx的,才好,所以我们这边先更新yum源,步骤如下: 1.添加yum源: [root@s ...
- Mac 下 安装 Nginx
---恢复内容开始--- Mac 下 安装nginx 首先确定自己有安装homebrew 安装 nginx brew install nginx 启动nginx 1.15版本下 安装是 直接在ngin ...