python的数据库链接池实现----DBUtilspython
DBUtils 属于WebWare项目的数据库链接池实现模块,用于对数据库链接线程化,使能够安全和有效的访问数据库的模块数据库
全局的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模块的依赖以下图所示:缓存
对典型的PyGreSQL模块依赖以下图所示:安全
DBUtils.SimplePooledDB 是一个很是简单的数据库链接池实现。他比完善的 PooledDB 模块缺乏不少功能。 DBUtils.SimplePooledDB 本质上相似于 MiscUtils.DBPool 这个Webware的组成部分。你能够把它看做一种演示程序。session
DBUtils.SteadyDB 是一个模块实现了"强硬"的数据库链接,基于DB-API 2创建的原始链接。一个"强硬"的链接意味着在链接关闭以后,或者使用次数操做限制时会从新链接。多线程
一个典型的例子是数据库重启时,而你的程序仍然在运行并须要访问数据库,或者当你的程序链接了一个防火墙后面的远程数据库,而防火墙重启时丢失了状态时。负载均衡
通常来讲你不须要直接使用 SteadyDB 它只是给接下来的两个模块提供基本服务, PersistentDB 和 PooledDB 。函数
DBUtils.PersistentDB 实现了强硬的、线程安全的、顽固的数据库链接,使用DB-API 2模块。以下图展现了使用 PersistentDB 时的链接层步骤:性能
当一个线程首次打开一个数据库链接时,一个链接会打开并仅供这个线程使用。当线程关闭链接时,链接仍然持续打开供这个线程下次请求时使用这个已经打开的链接。链接在线程死亡时自动关闭。fetch
简单的来讲 PersistentDB 尝试重用数据库链接来提升线程化程序的数据库访问性能,而且他确保链接不会被线程之间共享。
所以, PersistentDB 能够在底层DB-API模块并不是线程安全的时候一样工做的很好,而且他会在其余线程改变数据库会话或者使用多语句事务时一样避免问题的发生。
DBUtils.PooledDB 实现了一个强硬的、线程安全的、有缓存的、可复用的数据库链接,使用任何DB-API 2模块。以下图展现了使用 PooledDB 时的工做流程:
如图所示 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 的实例来设置一个特定数据库链接的生成器,床底以下参数:
举个例子,若是你正在使用 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 来设置数据库链接池,传递以下参数:
举个例子,若是你正在使用 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