您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:python自制简易mysql连接池的实现示例

51自学网 2022-02-21 10:49:29
  python
这篇教程python自制简易mysql连接池的实现示例写得很实用,希望能帮到您。

今天我们来说一点不一样的, 使用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 configparserimport 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 = localhostuser = rootpassword = 12345678database = practiceinitsize = 3maxsize = 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 = localhostuser = rootpassword = 12345678database = practiceinitsize = 3maxsize = 6
# 使用时...db = ThemisPool(fileName='myDB.cnf', configName='mysqlConfig')...

命名思路

Themis(忒弥斯) 取名来自于古希腊神话中秩序女神的名字, 就如同连接池的作用一样, 管理所有用户的连接, 减少不必要的损耗。

GitHub地址

ThemisPool连接池

以上就是本次的全部内容, 下版本将会解决 python 不能对 datetime 类型的数据进行 json格式化 的问题, 并将它集成进来

到此这篇关于python自制简易mysql连接池的实现示例的文章就介绍到这了,更多相关python mysql连接池内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


Django实现简单登录的示例代码
python调用文字识别OCR轻松搞定验证码
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。