python自制简易mysql连接池的实现示例
目录
- 连接池是什么?
- 为什么需要连接池?
- 连接池的原理是什么?
- 使用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
所有配置属性
参数
说明
类型
默认值
开始使用
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连接池
以上就是本次的全部内容, 下版本将会解决 python 不能对 datetime 类型的数据进行 json格式化 的问题, 并将它集成进来
到此这篇关于python自制简易mysql连接池的实现示例的文章就介绍到这了,更多相关python mysql连接池内容请搜索hwidc以前的文章或继国外高防服务器http://www.558idc.com/usa.html续浏览下面的相关文章希望大家以后多多支持hwidc!