内容简介:DBUtils是一个允许在多线程python应用和数据库之间安全及高效连接的python模块套件。DBUtils套件包含两个模块子集,一个适用于兼容DB-API 2接口的模块,一个适用于PyGreSQL的模块。
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模块在连接层并非线程安全的,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
参数创建连接池时,PooledDB将在不同线程间共享打开的数据库连接。但仍可以请求非线程共享的专用数据库连接。除了共享连接池外,还可以创建至少 mincached
个,至多 maxcached
个连接的空闲连接池,在 共享连接池未满 或线程请求专用数据库连接时使用。当某个线程关闭不再共享的连接时,该连接将返回到空闲连接池以便再次回收。
如果底层的DB-API 2模块非线程安全,将使用线程锁确保PooledDB连接是线程安全的。但对于线程专用的连接,要小心更改数据库会话或执行跨多个SQL指令的事务带来的不良影响。
要使用PoolDB模块,首先传递以下参数创建PoolDB实例:
When this maximum number is reached, connections are shared if they have been requested as shareable begin()
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()
如果 maxshared
参数设置了非0非None的值且 creator
参数设置的数据库模块支持连接共享,则连接池中的连接默认是线程间共享的。可以用以下方式获取线程专用连接:
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,因为这些框架自身维护了连接池。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽
- 数据库连接池
- 数据库连接池设置
- 怎样获知数据库的连接属性?
- 怎样获知数据库的连接属性?
- Laravel 使用多个数据库连接
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。