pymysql通过DBUtils实现连接池技术
DBUtils 是一套 Python 数据库连接池包,并允许对非线程安全的数据库接口进行线程安全包装。
一、安装
pip install DBUtils
二、导入模块
# 针对不同版本,可能导入方式存在差别 try: from dbutils.pooled_db import PooledDB from dbutils.persistent_db import PersistentDB except: from DBUtils.PooledDB import PooledDB from DBUtils.PersistentDB import PersistentDB
三、使用
-
DBUtils提供两种外部接口:
-
PersistentDB:
- 每当一个线程首次打开数据库连接时,都会创建一个新的数据库连接,并且该连接始终服务于该特定线程,直到该线程销毁,连接才会关闭
- 通过重用数据库连接来提高数据库的访问性能,同时确保了线程间不共享数据库连接(当线程数一定的情况下,推荐使用)
- 注意:避免短时间内创建多个线程(创建多个线程时,可使用延时操作)
- 实例化时常用参数设置:
import pymysql from dbutils.persistent_db import PersistentDB pool = PersistentDB(pymysql, host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USER, db=MYSQL_DATABASE, password=MYSQL_PASSWORD, charset='utf8mb4')
第一个参数指定的是连接数据库的模块pymysql,其它使用默认参数(maxusage=None或者0表示每个连接的使用次数不受限,ping=1表示每次获取连接时,检查连接是否可用...),后面都是使用pymysql中的参数
- 示例
import time import pymysql import threading from dbutils.persistent_db import PersistentDB from sc.common.config import * pool = PersistentDB(pymysql, host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USER, db=MYSQL_DATABASE, password=MYSQL_PASSWORD, charset='utf8mb4') id_set = set() # 统计连接池中的连接数 def test(): for i in range(100): con = pool.connection() id_set.add(id(con)) con.close() # 创建5个子线程 t_list = [] for i in range(5): t = threading.Thread(target=test) t_list.append(t) t.start() time.sleep(0.2) # 延时操作 for t in t_list: t.join() # 主线程操作 test() print(id_set) # 总共6个线程(1主+5子),6个连接:{1779330541312, 1779330540064, 1779330275744, 1779330276896, 1779330331120, 1779330276944}
-
PooledDB
- 能够提供线程间可共享的数据库连接,但是需要通过maxshared参数指定最多可共享连接数
- 对于应用中需要频繁地创建和销毁线程时,推荐使用
- 实例化常用参数设置:
import pymysql from dbutils.pooled_db import PooledDB pool = PooledDB(pymysql, maxconnections=10, blocking=True, host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USER, db=MYSQL_DATABASE, password=MYSQL_PASSWORD, charset='utf8mb4')
参数:
mincached:初始时连接池中的连接数,默认为0。 maxcached:连接池中最大的闲置连接数,默认为0表示不限制。 maxconnections:连接池允许的最大连接数,默认为0表示不限制。 blocking:当连接池达到最大连接数并且所有连接都在使用中时,是否阻塞等待可用连接,默认为False。 maxusage:单个连接的最大重复使用次数,默认为0表示不限制
- 示例(待补充)
-
-
使用连接池操作数据库
con = pool.connection() # 从池中获取数据库连接 cursor = con.cursor() # 创建游标 sql = '比如插入相关的sql语句' try: cursor.execute(sql, []) con.commit() except: con.rollback() finally: cursor.close() # 关闭游标 con.close() # 将数据库连接放回连接池(注意不是关闭该连接)
连接池pool最后不需要我们手动调用close()方法关闭,内部帮我们自动维护(__del__()方法中已实现self.close())