看了很多关于python连接池的文章,文章都写的很好,但唯一的遗憾是没有针对第一次接触链接池的朋友进行介绍的。最近有几个小朋友问我python链接池到底咋用,趁此记录下对链接池的入门理解;
链接池,首先他的作用是开一个连接通道,他的使用场景不仅仅是数据库。什么是通道?举个例子,python pymsql连接数据库执行一次查询,第一步程序需要连接数据库,第二步保持这个通道不断开并发送sql,第三步数据库执行后通过这个连接返回结果;
所以,通道也可以看作是一个连接,这点最明显的可以从MySQL show full processlist看出,MySQL show processlist展示的数据是当前数据库所有的连接和该连接的动作,有的是sleep状态,有的是在select等,他们的行数就是数据库此时的链接数,也就相当于数据库开了这么多个对外通道。
既然连接,那么必然有断开的时候,所以当一个窗口sql执行完了,那么新开的窗口在show processlist可能看不到之前的那个sql线程,因为那个线程执行完后连接断开了;
这样的发起连接 关闭连接,对于我们小数量级别几乎没有感知,但是首先要明白,每次新开一个连接数据库,都需要消耗性能,在针对高并发大流量的访问下,比如我们公司年底高峰期,qps达到3000,如果3000个同时重新开启连接那么对性能的消耗就比较大了,为了避免每次都要重新开启连接这种消耗的动作,出现了连接池;
链接池的主要作用是,保留一定链接数不和数据库断开,当应用需要访问数据库时,直接通过连接池拿取一个连通的连接,那么就避免了应用新开连接的消耗;
所以这个技术,不仅仅是给数据库用的,针对于此类原理的中间件也有链接池技术;但我们平时用得比较多的还是在数据库上;
所以,针对以上的话,上代码看比较好一点理解:
我新建了一个songsdb库和添加了一张空表;先查看当前连接状态:
通过python 查询空表后,查看数据库连接池状态:
代码:
import pymysql
from DBUtils.PooledDB import PooledDB,SharedDBConnection
import time
# while True:
pool = PooledDB(
creator=pymysql,
maxconnections=300,
mincached=10,
maxcached=5,
maxshared=5,
blocking=True,
maxusage=None,
ping=0,
host='localhost',
port=3306,
database='songsdb',
user='root',
password='123456',
charset='utf8'
)
def func():
conn = pool.connection()
cur = conn.cursor()
cur.execute('select * from t_os_songs_path')
re = cur.fetchall()
# time.sleep(100)
# conn.close()
print(re)
func()
执行成功,由于是空表,所以返回空:
查看执行后连接状态:
发现连接数和执行前的连接数一致?猜测原因是因为线程执行完后关闭了连接,并验证;验证方式,查询程序中加上sleep延时,让程序短时间不关闭,验证查询后连接是否会存在;操作,把上面代码的sleep注释取消,延长程序执行时间,并查看数据库连接;
分析结果我们可以得到以下几个结论:
1、连接不手动关闭的情况下,执行完sql,数据库是不会关闭连接的,连接需要服务端发起关闭
2、服务端不显示的指定close,但是线程执行完后,服务线程被回收,数据库连接也会被关闭
3、显示的close会关闭连接
那么映射出来,我们能得到信息还有,如果线程不会死掉,有没有显示的关闭连接,那么连接就会一致存在,当链接数超过数据库限制的时候,无法创建新的连接程序会报错,这对程序的严谨性有一定的要求;
那么正题到了,pothon连接池怎么用?
python3的链接池可用的模块有:DBUtils
他有两种模式:
模式一:为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程再次使用。当线程终止时,连接自动关闭。 模式二:创建一批连接到连接池,供所有线程共享使用。
模式以对多线程有要求,我比较常用第二个,启用链接池写法如下:
import pymysql
from DBUtils.PooledDB import PooledDB,SharedDBConnection
pool = PooledDB(
creator=pymysql,pymysql连接数据库模块
maxconnections=300, 最大连接数
mincached=10, 最小缓存的空闲链接数
maxcached=15, 最大缓存的空闲链接数
maxshared=0,链接池中最多共享的链接数量,0和None表示全部共享
blocking=True,连接池中如果没有可用连接后,是否阻塞等待
maxusage=None,连接可被重复使用数,None不限制
ping=0,检查数据库能否连接
host='localhost',
port=3306,
database='songsdb',
user='root',
password='123456',
charset='utf8'
)
以上就可以启动一个数据库连接池了,但是,我们只要程序线程执行完会自动close连接,为了保持连接的存在,我们需要让连接池线程不结束,所以写个while true:执行如下脚本,查看数据库:
import pymysql
from DBUtils.PooledDB import PooledDB,SharedDBConnection
while True:
pool = PooledDB(
creator=pymysql,
maxconnections=300,
mincached=10,
maxcached=15,
maxshared=15,
blocking=True,
maxusage=None,
ping=0,
host='localhost',
port=3306,
database='songsdb',
user='root',
password='123456',
charset='utf8'
)
数据库开启了不会被关掉的连接,这时候我们程序就启动了一个活动的连接池,接下来其他服务只需要去连接词取连接即可,取的方法如下:
conn = pool.connection()
cur = conn.cursor()
当然,可以把连接池封装到一个py文件中,其他的文件也可以调用
当然关闭这个连接:
conn.close()
注意这个close是连接词connection的conn的close,不是pymysql的close,这样我们使用完连接后,关闭连接链接池会自动回收提供个下一个服务使用;