Python数据库链接池模块-----DBUtils使用

python的数据库链接池实现----DBUtilspython

DBUtils 属于WebWare项目的数据库链接池实现模块,用于对数据库链接线程化,使能够安全和有效的访问数据库的模块数据库

DBUtils其实是一个包含两个子模块的Python包,一个用于链接DB-API 2模块,另外一个用于链接典型的PyGreSQL模块。
 
全局的DB-API 2变量
SteadyDB.py 用于稳定数据库链接
PooledDB.py 链接池
PersistentDB.py 维持持续的数据库链接
SimplePooledDB.py 简单链接池
典型的 PyGreSQL 变量
SteadyPg.py 稳定PyGreSQL链接
PooledPg.py PyGreSQL链接池
PersistentPg.py 维持持续的PyGreSQL链接
SimplePooledPg.py 简单的PyGreSQL链接池

对标准DB-API 2模块的依赖以下图所示:缓存

dbdep.gif

对典型的PyGreSQL模块依赖以下图所示:安全

pgdep.gif

SimplePooledDB

DBUtils.SimplePooledDB 是一个很是简单的数据库链接池实现。他比完善的 PooledDB 模块缺乏不少功能。 DBUtils.SimplePooledDB 本质上相似于 MiscUtils.DBPool 这个Webware的组成部分。你能够把它看做一种演示程序。session

SteadyDB

DBUtils.SteadyDB 是一个模块实现了"强硬"的数据库链接,基于DB-API 2创建的原始链接。一个"强硬"的链接意味着在链接关闭以后,或者使用次数操做限制时会从新链接。多线程

一个典型的例子是数据库重启时,而你的程序仍然在运行并须要访问数据库,或者当你的程序链接了一个防火墙后面的远程数据库,而防火墙重启时丢失了状态时。负载均衡

通常来讲你不须要直接使用 SteadyDB 它只是给接下来的两个模块提供基本服务, PersistentDB 和 PooledDB 。函数

PersistentDB

DBUtils.PersistentDB 实现了强硬的、线程安全的、顽固的数据库链接,使用DB-API 2模块。以下图展现了使用 PersistentDB 时的链接层步骤:性能

persist.gif

当一个线程首次打开一个数据库链接时,一个链接会打开并仅供这个线程使用。当线程关闭链接时,链接仍然持续打开供这个线程下次请求时使用这个已经打开的链接。链接在线程死亡时自动关闭。fetch

简单的来讲 PersistentDB 尝试重用数据库链接来提升线程化程序的数据库访问性能,而且他确保链接不会被线程之间共享。

所以, PersistentDB 能够在底层DB-API模块并不是线程安全的时候一样工做的很好,而且他会在其余线程改变数据库会话或者使用多语句事务时一样避免问题的发生。

PooledDB

DBUtils.PooledDB 实现了一个强硬的、线程安全的、有缓存的、可复用的数据库链接,使用任何DB-API 2模块。以下图展现了使用 PooledDB 时的工做流程:

pool.gif

如图所示 PooledDB 能够在不一样线程之间共享打开的数据库链接。这在你链接并指定 maxshared 参数,而且底层的DB-API 2接口是线程安全才能够,可是你仍然可使用专用数据库链接而不在线程之间共享链接。除了共享链接之外,还能够设立一个至少 mincached 的链接池,而且最多容许使用 maxcached 个链接,这能够同时用于专用和共享链接池。当一个线程关闭了一个非共享链接,则会返还到空闲链接池中等待下次使用。

若是底层DB-API模块是非线程安全的,线程锁会确保使用 PooledDB 是线程安全的。因此你并不须要为此担忧,可是你在使用专用链接来改变数据库会话或执行多命令事务时必须当心。

该选择哪个?

PersistentDB 和 PooledDB 都是为了重用数据库链接来提升性能,并保持数据库的稳定性。

因此选择何种模块,能够参考上面的解释。 PersistentDB 将会保持必定数量的链接供频繁使用。在这种状况下你老是保持固定数量的链接。若是你的程序频繁的启动和关闭线程,最好使用 PooledDB 。后面将会提到更好的调整,尤为在使用线程安全的DB-API 2模块时。

固然,这两个模块的接口是很类似的,你能够方便的在他们之间转换,并查看哪一个更好一些。

使用方法

全部模块的使用方法都很类似,可是在初始化 "Pooled" 和 "Persistent" 时还有有些不一样,尤为是DB-API和PyGreSQL之间。

这里只讲解 PersistentDB 和更复杂的 PooledDB 模块。其余模块的细节请参与其文档。使用Python解释器控制台,你能够显示 PooledDB 的文档,以下:

help(PooledDB)

PersistentDB

为了使用 PersistentDB 你首先须要经过建立 PersistentDB 的实例来设置一个特定数据库链接的生成器,床底以下参数:

  • creator: 可使用任意返回 DB-API 2 链接对象的函数活 DB-API 2 兼容的数据库模块。
  • maxusage: 一个链接最大容许复用次数(缺省为 0 或 False 意味着无限制的重用),当达到限制时,将会从新链接数据库
  • setsession: 一个可选的SQL命令列表能够用于准备会话,如 ["set datestyle to german", ...]
  • creator 函数或生成 DB-API 2 链接的函数,能够接受这里的附加参数,好比主机名、数据库、用户名、密码等等。你也能够选择传递给 creator 的其余参数,并容许提供失败重连和负载均衡。

举个例子,若是你正在使用 pgdb 做为数据库模块并想要链接本机数据库 mydb ,容许重用1000次:

import pgdb # import used DB-API 2 module
from DBUtils.PersistentDB import PersistentDB
persist = PersistentDB(pgdb, 1000, database='mydb')

按照如上设置完成了链接生成器以后,你能够按照以下来请求一个链接:

db = persist.connection()

你可使用这些链接就像使用原始的DB-API 2链接同样。实际上你获得的是一个经过``SteadyDB``获得的强硬的链接,基于DB-API 2。

关闭一个强硬的链接使用 db.close() ,这在内部实际上被忽略掉了,而且供下次使用。在线程关闭时,也会自动关闭数据库链接。你能够改变这个行为经过 persist._closeable 为 True 。

PooledDB

为了使用 PooledDB 模块,你首先须要经过建立 PooledDB 来设置数据库链接池,传递以下参数:

  • creator: 能够生成 DB-API 2 链接的任何函数或 DB-API 2 兼容的数据库链接模块。
  • mincached : 启动时开启的空链接数量(缺省值 0 意味着开始时不建立链接)
  • maxcached: 链接池使用的最多链接数量(缺省值 0 表明不限制链接池大小)
  • maxshared: 最大容许的共享链接数量(缺省值 0 表明全部链接都是专用的)若是达到了最大数量,被请求为共享的链接将会被共享使用。
  • maxconnections: 最大容许链接数量(缺省值 0 表明不限制)
  • blocking: 设置在达到最大数量时的行为(缺省值 0 或 False 表明返回一个错误;其余表明阻塞直到链接数减小)
  • maxusage: 单个链接的最大容许复用次数(缺省值 0 或 False 表明不限制的复用)。当达到最大数值时,链接会自动从新链接(关闭和从新打开)
  • setsession: 一个可选的SQL命令列表用于准备每一个会话,如 ["set datestyle to german", ...]
  • creator 函数或能够生成链接的函数能够接受这里传入的其余参数,例如主机名、数据库、用户名、密码等。你还能够选择传入creator函数的其余参数,容许失败重连和负载均衡。

举个例子,若是你正在使用 pgdb 做为DB-API模块,并但愿链接池中至少有5个链接到数据库 mydb

import pgdb # import used DB-API 2 module
from DBUtils.PooledDB import PooledDB
pool = PooledDB(pgdb, 5, database='mydb')

一旦设置好了链接池,你就能够按照以下请求一个链接:

db = pool.connection()

你可使用这些链接有如原始的DB-API 2同样。而实际使用的是``SteadyDB``版本的强硬链接。

请注意链接能够与其余线程共享,只要你设置 maxshared 参数为非零,而且DB-API 2模块也容许。若是你想要使用专用链接则使用:

db = pool.connection(0)

若是你再也不须要这个链接了,则能够返回给链接池使用 db.close() 。你也可使用相同的方法获取另外一个链接。

警告: 在一个多线程环境,不要使用下面的方法:

pool.connection().cursor().execute(...)

这将会致使过早的释放链接以供复用,并且若是是非线程安全还会出错。确保链接对象在你的使用过程当中是一直存在的,例如:

db = pool.connection()
cur = db.cursor()
cur.execute(...)
res = cur.fetchone()
cur.close() # or del cur
db.close() # or del db
相关文章
相关标签/搜索