python数据库连接工具DBUtils

DBUtils是一个允许在多线程python应用和数据库之间安全及高效连接的python模块套件。

模块

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框架,如SQLObjectSQLAlchemy,不需要使用DBUtils,因为这些框架自身维护了连接池。

数据库线程安全级别:

比如pymysql就是可以共享模块但不能共享连接,查看方式pymysql.threadsafety

https://segmentfault.com/a/1190000017952033

DBUtil内部实现过程解读的更多相关文章

  1. 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程

    [前提] 想要实现使用某种语言,比如Python,C#等,去实现模拟登陆网站的话,首先要做的事情就是使用某种工具,去分析本身使用浏览器去登陆网页的时候,其内部的执行过程,内部逻辑. 此登陆的逻辑过程, ...

  2. CLRMonitor - 跟踪CLR内部执行过程工具

    CLRMonitor v1.0.1511.13 点击此处下载 软件介绍:这款软件主要用于跟踪CLR内部执行过程,定位当前程序执行的命名空间以及方法名等信息.可以迅速找到被跟踪程序的当前执行方法名.本软 ...

  3. 【Spring-web】RestTemplate源码学习——梳理内部实现过程

    2016-12-28 by 安静的下雪天  http://www.cnblogs.com/quiet-snowy-day/p/6228198.html  提示:使用手机浏览时请注意,图多费流量. 本篇 ...

  4. ORACLE之SQL语句内部解析过程【weber出品】

    一.客户端通过监听连接到数据库,数据库开启一个server process进程来接收客户端传过来的sql. 1.这条sql语句从来都没有被执行过.(硬解析) 2.这条sql语句被执行过.(软解析) 二 ...

  5. STM32启动过程解读与跟踪验证

    经过查阅各种官方文献和对代码进行单步跟踪,详细地叙述了STM32加电启动的具体过程.对于关键性的语句都指明了出处.下面将学习成果分享给大家,由于笔者知识有限,不当之处敬请指出. 为了更好的说明问题,先 ...

  6. HttpApplication 对象的创建过程及HttpModule过滤器的内部实现过程

    最近通过Reflector学习了一下asp.net内部的原理,做做笔记,方便以后查阅. 先看下HttpApplication 对象的创建过程 从IHttpHandler applicationInst ...

  7. 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?

    先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...

  8. Struts2内部执行过程

    首先是Struts2的流程图. 一.当有一个请求的时候.执行以下流程. 1 客户端初始化一个指向Servlet容器的请求: 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做Act ...

  9. mysql系列二、mysql内部执行过程

    向MySQL发送一个请求的时候,MySQL到底做了什么 客户端发送一条查询给服务器. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器端进行SQL解析.预 ...

随机推荐

  1. Song Form

    First of all, song form is an indepentent concept from the boxes, boxes simply describe the way the ...

  2. nginx url默认去掉index.php

  3. machine learning(8) -- classification

    分类预测不能使用linear regression, linear regression算法对于分类预测效果很差,应使用logistic regression算法 Logistic regressti ...

  4. PHP搭建大文件切割分块上传功能示例

    转载:https://www.jb51.net/article/101931.htm 背景 在网站开发中,文件上传是很常见的一个功能.相信很多人都会遇到这种情况,想传一个文件上去,然后网页提示“该文件 ...

  5. git 和 svn比较

    SVN和Git 介绍,区别,优缺点,适用范围总结 原创 2016年01月29日 15:17:36 15774   介绍   SVN SVN是Subversion的简称,是一个开放源代码的版本控制系统, ...

  6. Java中CAS-ABA的问题解决方案

    忻州SEO摘要 CAS即对比交换,它在保证数据原子性的前提下尽可能的减少了锁的使用,很多编程语言或者系统实现上都大量的使用了CAS.   了解CAS(Compare-And-Swap) CAS即对比交 ...

  7. Navicat连接Oracle报ORA-12737错误

    替换oci.dll 文件分享百度网盘:链接:https://pan.baidu.com/s/1wayojGlKcgdMRZTvBqAUgw 密码:3d6j 把下载的文件放到Navicat文件夹里,然后 ...

  8. /etc/sysconfig/network-scripts/ifcfg-ensxx

    TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=static # 获取ip的方式,static表示静态设置的ip,还有dhcp,系统 ...

  9. centos7的redis加哨兵系统

    三台服务器 1.下载 wget http://download.redis.io/releases/redis-5.0.3.tar.gztar -zxvf redis-5.0.3.tar.gzcd r ...

  10. unbuntu16.04安装geoserver运行环境

    1.下载并上传 在windows下载geoserver 2.15.1Platform Independent Binary版本, 是zip文件,然后使用xfile将zip上传到/usr/geoserv ...