1. 程式人生 > >淺析資料庫連線池原理分析與實現

淺析資料庫連線池原理分析與實現

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 參考文獻