Python 数据库连接池

一、自己实现的一个简单的连接池
简单概括:其他还好,稳定性有待验证

import pymysql

class SqlPool:
    _singleton = None
    _conn = {}  # 连接池字典
    _js = {}  # 连接数量字典
    _minSize = 3  # 空闲时的连接数,需要最大连接达到
    _maxSize = 10  # 最大连接数

    def __new__(cls, *args, **kwargs):
        if not cls._singleton:
            cls._singleton = super(SqlPool, cls).__new__(cls)
        return cls._singleton

    def __init__(self, name):
        # name:数据库名称
        self.re_conn(name)

    def re_conn(self, name, res=False):
        _conn = self._conn
        _js = self._js
        self.name = name
        if name not in _conn or res:
            _conn[name] = []
            _js[name] = 0
        if not _conn[name] and _js[name] <= self._maxSize:
            conn = pymysql.connect(db=name, user=config['U']['us'], passwd=config['U']['ps'],
                                                host=config['U']['hs'],
                                                charset='utf8')
            _conn[name].append(conn)
            _js[name] += 1

    def get_conn(self, name,closed=False):
        ''' 获取连接 '''
        _conn = self._conn
        if closed:
            self.re_conn(name, res=True)
        if name not in _conn or not _conn[name]:
            self.re_conn(name)
        conn = _conn[name].pop()
        return conn

    def set_conn(self, name, conn):
        ''' 每使用完连接后,需回收连接 '''
        _conn = self._conn[name]
        l_c = len(_conn)
        if l_c < self._minSize:
            _conn.append(conn)
        else:
            _js = self._js[name]
            _js = _js-1 if _js>0 else l_c
            conn.close()

def test():
    sp = SqlPool('db_name')
    conn = sp.get_conn('db_name')
    cur = conn.cursor()
    cur.execute('select * from tables')
    sp.set_conn('db_name',conn)
    return cur.fetchall()

二、使用 python 模块 DBUtils 来实现


1,PersistentDB
# 简单概括:性能稍好,稳定性稍有不足

from DBUtils.PersistentDB import PersistentDB
import pymysql

Pool = PersistentDB(
    creator = pymysql,  # 使用连接数据库的模块
    maxusage = None,    # 一个连接最多被使用的次数,None为无限制
    setsession = [],    # 开始会话前执行的命令
    ping = 0,           # ping MySQL服务端,检查服务是否可用
    closeable = False,  # conn.close() 被忽略,供下次使用,直到线程关闭,自动关闭连接。而等于True时,conn.close()真的被关闭
    threadlocal = None, # 本线程独享值的对象,用于保存连接对象
    host = 'localhost',
    port = 3306,
    user = 'root',
    passwd = '123456',
    db = 'test',
    charset = 'utf8'
    )

2,PooledDB
# 简单概括:稳定性稍好,性能稍有不足

import time
import pymysql
import threading
from DBUtils.PooledDB import PooledDB,SharedDBConnection

POOL = PooledDB(
    creator = pymysql, #使用链接数据库的模块
    maxconnections = 6,  #连接池允许的最大连接数,0和None表示没有限制
    mincached = 2, #初始化时,连接池至少创建的空闲的连接,0表示不创建
    maxcached = 5, #连接池空闲的最多连接数,0和None表示没有限制
    maxshared = 3, #连接池中最多共享的连接数量,0和None表示全部共享,ps:其实并没有什么用,因为pymsql和MySQLDB等模块中的threadsafety都为1,所有值无论设置多少,_maxcahed永远为0,所以永远是所有链接共享
    blocking = True, #链接池中如果没有可用共享连接后,是否阻塞等待,True表示等待,False表示不等待然后报错
    setsession = [],#开始会话前执行的命令列表
    ping = 0,#ping Mysql 服务端,检查服务是否可用
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    passwd = '123456',
    db = 'test',
    charset = 'utf8'
)

def func():
    #检测当前正在运行的连接数是否小于最大的连接数,如果不小于则等待连接或者抛出raise TooManyConnections异常
    #否则优先去初始化时创建的连接中获取连接SteadyDBConnection
    #然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回
    #如果最开始创建的连接没有链接,则去创建SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回
    #一旦关闭链接后,连接就返回到连接池让后续线程继续使用
    conn = POOL.connection()
    cursor = conn.cursor()
    cursor.execute('select * from table')
    result = cursor.fetchall()
    print(result)
    conn.close()
func()

猜你喜欢

转载自blog.csdn.net/a649344475/article/details/81273382
今日推荐