浅析数据库连接池原理分析与实现 - PyMySQL + DBUtils

1 动机

在项目初期对于数据库的使用就是打开一个连接并进行使用,使用过后关闭连接释放资源,并且在后台简单测试中,并没有出现问题。但是在与前端对接之后,发现频繁地打开和关闭连接会对性能造成很大的影响,而且之前假设的情况是接受的请求都是同步的,但是前端可能发送异步请求,当两个请求同时到达时,甚至会导致数据库故障。

基于以上原因,就不得不使得我们去考虑使用数据库连接池的方法。

2 数据库连接池原理

首先,简单介绍一下数据库连接池的基本原理:最初,打开一定数量的数据库连接(最小连接数),当收到调用者的调用请求之后,分配给调用者,在调用完毕之后将连接返回到连接池(返回到连接池的连接不会关闭,而是为下一次的调用而分配)。

因此,可以发现数据库连接池节省了大量数据库连接打开与关闭的操作,同时也保证了异步调用不会导致数据库崩溃。

3 数据库连接池实现 (PyMySQL + DBUtils)

3.1 参数设定

参数设定使用 json 存储:

{
    "db":{
        "host":"db",
        "port":3306,
        "user":"root",
        "password":"xxx",
        "database":"xxx",
        "charset":"utf8"
    },
    "db_pool":{
        "mincached":5,
        "maxcached":5,
        "maxshared":10,
        "maxconnecyions":20,
        "blocking"=1,
        "maxusage"=0
    }
}

json 读取:

import json

class Tools:
    ...
    def get_config(self, file_name="config"):
        """Get Configuration"""
        with open(file_name, "r", encoding="utf-8") as f:
            config = json.load(f)
        return config

3.2 (PyMySQL + DBUtils) 数据库连接池类

import pymysql
from DBUtils.PooledDB import PooledDB
from tools import Tools

# create tools
tools = Tools()

# load jsons
conf_path = '...'
conf = tools.get_config(file_name=conf_path)

class DBPool(object):
    __pool = None
    def __init__(self):
        # 构造函数,创建数据库连接、游标
        self.coon = DBPool.getmysqlconn()
        self.cur = self.coon.cursor(cursor=pymysql.cursors.DictCursor)

    # 数据库连接池连接
    @staticmethod
    def getmysqlconn():
        if DBPool.__pool is None:
            __pool = PooledDB(creator=pymysql, mincached=conf['db_pool']['mincached'],
                              maxcached=conf['db_pool']['maxcached'], 
                              maxshared=conf['db_pool']['maxshared'],
                              maxconnections=conf['db_pool']['maxconnections'],
                              blocking=conf['db_pool']['blocking'], 
                              maxusage=conf['db_pool']['maxusage'], setsession=None,
                              host=conf['db']['host'], port=conf['db']['port'], 
                              user=conf['db']['user'], passwd=conf['db']['password'],
                              db=conf['db']['database'], charset=conf['db']['charset'])
        return __pool.connection()

    # 插入\更新\删除 sql
    def op_modify(self, sql):
        insert_num = self.cur.execute(sql)  # 执行sql
        self.coon.commit()
        return insert_num

    # 查询
    def op_select(self, sql):
        self.cur.execute(sql)  # 执行sql
        select_res = self.cur.fetchall()  # 返回结果为字典
        return select_res

    # 释放资源
    def dispose(self):
        self.coon.close()
        self.cur.close()

3.3 数据库连接池 DBPool 类的使用

if __name__ =='__main__':
    # 申请资源
    dbpOpt = dbPool()
    # select opt
    sql = "SELECT ..."
    results = dbpOpt.op_select(sql)
    # modify opt
    sql = "UPDATE ..."
    results = dbpOpt.op_modify(sql)
    # 释放资源
    dbpOpt.dispose()

4 参考文献

  • wikipedia
  • 数据库连接池(Connection Pool)
  • 几种常见数据库连接池的使用比较
  • 数据库连接池原理详解与自定义连接池实现

你可能感兴趣的:(系统分析与设计作业)