python自制简易mysql连接池的实现示例
作者:末日沙兔 发布时间:2023-04-14 20:23:55
目录
连接池是什么?
为什么需要连接池?
连接池的原理是什么?
使用python语言自制简易mysql连接池
开始使用
自定义配置文件名 & 配置标签
命名思路
GitHub地址
今天我们来说一点不一样的, 使用python语言手撸mysql连接池.
连接池是什么?
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。在并发量足够时连接池一般比直接连接性能更优, 不仅提高了性能的同时还管理了宝贵的资源.
为什么需要连接池?
讨论这个问题时, 我们需要先了解高并发导致服务器卡顿的原因出在哪里.
正常情况下, 每当一位用户使用各类终端连接到服务器的时候, 服务器都需要开辟一片内存为其服务, 每当一个请求从前端传入都需在mysql之间创建一条连接. 然而过多的连接会导致服务器卡顿内存占用过高, 这时候就需要连接池对所有连接状态进行管理, 合理分配&回收资源.
简单说就是使用连接池技术可用减少服务器压力.
连接池的原理是什么?
连接池主要需要两个参数,默认连接数、最大连接数
当服务启动时, 首先创建默认连接数的空闲连接放入池中.
当用户需要连接时, 首先查看池中是否有空闲连接.
如果小于: 创建新连接交付用户使用.
如果等于: 线程阻塞, 等待有空闲连接再交予用户.
如果有: 由连接池分配从池中取出一个空闲连接交付用户使用.
如果没有: 查看当前存活的所有连接总数是否大于最大连接.
当用户用完连接后, 查看当前存活连接数是否大于默认值.
如果小于等于: 将此条连接重新放入空闲池中, 等待下一次使用.
如果大于: 将此条连接释放销毁, 不放入池中.
使用python语言自制简易mysql连接池
这里, 我们需要 ThemisPool.py 连接池本身, db.cnf 配置文件, 其目录路径如下:
# 推荐目录格式, ThemisPool.py & db.cnf 只需要在同级目录下即可
[your python project]
|
|
|-- util
|
|-- db.cnf
|
|-- ThemisPool.py
ThemisPool.py
# 导入依赖
# mysql连接基本库
import pymysql
# 读取配置文件所需要的库
import configparser
import os
# 线程管理所需要的库
import threading
# 创建配置类用户读取配置文件
class Config(object):
def __init__(self, configFileName='db.cnf'):
file = os.path.join(os.path.dirname(__file__), configFileName)
self.config = configparser.ConfigParser()
self.config.read(file)
def getSections(self):
return self.config.sections()
def getOptions(self, section):
return self.config.options(section)
def getContent(self, section):
result = {}
for option in self.getOptions(section):
value = self.config.get(section, option)
result[option] = int(value) if value.isdigit() else value
return result
# 将连接所需要的参数封装在对象中
# 依次为: 数据库密码、需要连接的库名、主机地址[默认 localhost]、端口号[默认 3306]、初始化连接数[默认 3]、最大连接数[默认 6]
class parameter(object):
def __init__(self, password, database, host="localhost",port="3306" user="root", initsize=3, maxsize=6):
self.host = str(host)
self.port = int(port)
self.user = str(user)
self.password = str(password)
self.database = str(database)
self.maxsize = int(maxsize)
self.initsize = int(initsize)
# 连接池
class ThemisPool(parameter):
def __init__(self, fileName='db.cnf', configName='mysql'):
# 加载配置文件, 配置文件名默认为 'db.cnf', 配置标签默认为 'mysql'
self.config = Config(fileName).getContent(configName)
super(ThemisPool, self).__init__(**self.config)
# 创建队列作为 池
self.pool = queue.Queue(maxsize=self.maxsize)
self.idleSize = self.initsize
# 创建线程锁
self._lock = threading.Lock()
# 初始化连接池
for i in range(self.initsize):
# 创建 初始化连接数 数量的连接放入池中
self.pool.put(self.createConn())
# 启动日志
print('\033[1;32m ThemisPool connect database {database}, login is {user} \033[0m'.format(database=self.database,
user=self.user))
# 生产连接
def createConn(self):
# 使用mysql基本类
# pymysql.connect 参数这里不做解释,具体请查阅官网 https://pypi.org/project/PyMySQL/
return pymysql.connect(host=self.host,
port=self.port,
user=self.user,
password=self.password,
database=self.database,
charset='utf8')
# 获取连接
def getConn(self):
self._lock.acquire()
try:
# 如果池中连接够直接获取
if not self.pool.empty():
self.idleSize -= 1
else:
# 否则重新添加新连接
if self.idleSize < self.maxsize:
self.idleSize += 1
self.pool.put(self.createConn())
finally:
self._lock.release()
return self.pool.get()
# 释放连接
def releaseCon(self, conn=None):
try:
self._lock.acquire()
# 如果池中大于初始值就将多余关闭,否则重新放入池中
if self.pool.qsize() < self.initsize:
self.pool.put(conn)
self.idleSize += 1
else:
try:
# 取出多余连接并关闭
surplus = self.pool.get()
surplus.close()
del surplus
self.idleSize -= 1
except pymysql.ProgrammingError as e:
raise e
finally:
self._lock.release()
# 拉取数据(查询)
# 可用语句类型 (select)
def fetchone(self, sql):
themis = None
cursor = None
try:
themis = self.getConn()
cursor = themis.cursor()
cursor.execute(sql)
return cursor.fetchall()
except pymysql.ProgrammingError as e:
raise e
except pymysql.OperationalError as e:
raise e
except pymysql.Error as e:
raise e
finally:
cursor.close()
self.releaseCon(themis)
# 更新
# 可用语句类型 (insert, update, delete)
def update(self, sql):
themis = None
cursor = None
try:
themis = self.getConn()
cursor = themis.cursor()
cursor.execute(sql)
return cursor.lastrowid
except pymysql.ProgrammingError as e:
raise e
except pymysql.OperationalError as e:
raise e
except pymysql.Error as e:
raise e
finally:
themis.commit()
cursor.close()
self.releaseCon(themis)
# 释放连接池本身
def __del__(self):
try:
while True:
conn = self.pool.get_nowait()
if conn:
conn.close()
except queue.Empty:
pass
db.cnf 配置文件
[mysql]
host = localhost
user = root
password = 12345678
database = practice
initsize = 3
maxsize = 6
所有配置属性
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
host | 主机地址 | str | localhost |
port | 端口号 | int | 3306 |
user | mysql登录用户名 | str | root |
password | mysql登录密码 | str | - |
database | 访问库名 | str | - |
initsize | 初始化连接数 | int | 3 |
maxsize | 最大连接数 | int | 6 |
开始使用
from util.ThemisPool import ThemisPool
# 初始化ThemisPool连接池 (Initialize the ThemisPool connection pool)
db = ThemisPool()
# 查询拉取数据,函数会直接返回数据 (Query pull data.It returns data directly)
selectSql = "select * from user;"
data = db.fetchone(selectSql)
# 增、删、改语句, 如果有使用mysql自增长插入的值函数会返回自增长的数据 (insert,upate delete and alter. If there is a value function inserted using mysql self-growth, it will return self-growth data)
insertSql = "insert into user values(null,'user001','123456')"
id = db.update(selectSql)
自定义配置文件名 & 配置标签
配置文件名默认为 db.cnf, 配置标签默认为 [mysql]
例如自定义配置文件名为 myDB.cnf, 配置标签为 [mysqlConfig]
# myDB.cnf
[mysqlConfig]
host = localhost
user = root
password = 12345678
database = practice
initsize = 3
maxsize = 6
# 使用时
...
db = ThemisPool(fileName='myDB.cnf', configName='mysqlConfig')
...
命名思路
Themis(忒弥斯) 取名来自于古希腊神话中秩序女神的名字, 就如同连接池的作用一样, 管理所有用户的连接, 减少不必要的损耗。
GitHub地址
ThemisPool连接池
来源:https://juejin.cn/post/7022684526891499528
猜你喜欢
- 更换域名,估计是很多站长都很头疼的事情。通常大家的做法就是把老的域名通过IIS设置做301跳转到新的域名。对于只有一个虚拟空间的站长来说,换
- BeautifulSoup简介Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:Beautif
- 在按钮旁边加文字1.打开editor/js/ 两个js文件fckeditorcode_gecko.js fckeditorcode_ie.j
- 我们经常见到很多网站留言系统的显示访客的IP地址都是隐藏了一部分,以达到隐蔽访客真实地理位置的功能。如:111.222.333.*,当然在系
- 一、sh是什么SH是一个独特的子进程包装器,可将您的系统程序动态映射到Python函数。SH帮助您用Python编写Shell脚本,既能支持
- 文章主要描述的是SQL Server到DB2连接服务器的正确实现过程,以及对其在实际操作中所要用到的实际操作环境的描述,以下就是对SQL S
- MySQL Group By用法我们现在回到函数上。记得我们用 SUM 这个指令来算出所有的 Sales (营业额)吧!如果我们的需求变成是
- 程序只要在运行,就免不了会出现错误,错误很常见,比如Error,Notice,Warning等等。在PHP中,主要有以下3种错误类型。1.注
- 为了安全我们经常给access数据库加上密码,这样就算让本人下载了数据库,那么想看到数据库中的数据也不是那么简单的,起码多了一层障碍!我们平
- 【译者的话】 作为一家非盈利性的防止青少年 * 的机构, Five Alive 希望拥有一个独特的标志来配合机构的宣传。他们决定在网站上通过竞
- 之前,我们在另外一篇文章中使用Prim算法生成了一个完美迷宫,利用的是遍历网格的方法,这一次,我们要教教大家用遍历墙的方法生成,上一篇文章链
- 如下所示:matplotlib.pyplot.plot(*args, **kwargs)绘制线条或标记的轴。参数是一个可变长度参数,允许多个
- 这篇分享几个在地址栏实现的Javascript有趣效果和应用。能在浏览器地址栏实现的效果太多了,字体放大、显示所有图片、显示Cookie等等
- 手写数字识别算法import pandas as pdimport numpy as npfrom sklearn.neural_netwo
- 通过session,我们可以在多次浏览器请求中保持数据, 接下来的部分就是用session来处理用户登录了。 当然,不能仅凭用户的一面之词,
- 本文实例讲述了Python日期时间Time模块。分享给大家供大家参考,具体如下:关于时间和日期模块python程序能用很多方式处理日期和时间
- 为满足用户的视觉追求及产品的背景图片的换肤功能,设计师难免在设计上会用到半透明的效果。因此页面重构师基于视觉及产品的需要,采用了PNG32的
- asp vbs Cache缓存类属性valid,是否可用,取值前判断属性name,cache名,新建对象后赋值方法add(值,到期时间),设
- 由于项目收尾,最近忙着做一些方法的优化,整理了一些分享给大家。 当页面内有许多控件,我们在需要清空其值的时候,一个个清空未免太麻烦。于是写了
- PHP中重定向网页跳转页面的方法(共三种)第一种:利用header()函数进行重定向,这也是我用的较多的。(注意!locationhe和“: