python利用DBUtils实现数据库连接池

连接池与DButils介绍

当我们在运用python通过HTTP连接与mysql这类数据库进行短暂连接时,因为可能就只是插入或者读取某些数据,所以读取完成后便关闭,并不需要考虑太多性能问题。但如果是在没有框架的情况下,在一个函数里用原生SQL通过比方说pymysql、Cmysql等模块频繁进行连接操作,那么效率就会很低,因为需要频繁验证HTTP服务,甚至可能会发生报错,由于线程可能发生堵塞,所以这里就有了数据库连接池的概念,通过它进行连接复用。

一说到数据库连接池,java 中有很多选择,C3P0、DBCP、Proxool、Tomcat-JDBC、druid 等等等等,五花八门,但python中似乎只有DBUtils。DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块。DBUtils已经作为 Webware for Python 一部分用来结合 PyGreSQL 访问 PostgreSQL 数据库,当然他也可以用在其他Python应用程序中来访问 DB-API 2 兼容的数据库接口。

DBUtils接口与参数

DBUtils提供两种外部接口:

  • PersistentDB :提供线程专用的数据库连接,并自动管理连接。
  • PooledDB :提供线程间可共享的数据库连接,并自动管理连接。

一般常用的参数如下:

  • creator: 可以生成 DB-API 2 连接的任何函数或 DB-API 2 兼容的数据库连接模块。
  • mincached : 启动时开启的空连接数量(缺省值 0 意味着开始时不创建连接)
  • maxcached: 连接池使用的最多连接数量(缺省值 0 代表不限制连接池大小)
  • maxshared: 最大允许的共享连接数量(缺省值 0 代表所有连接都是专用的)如果达到了最大数量,被请求为共享的连接将会被共享使用。
  • maxconnections: 最大允许连接数量(缺省值 0 代表不限制)
  • blocking: 设置在达到最大数量时的行为(缺省值 0 或 False 代表返回一个错误;其他代表阻塞直到连接数减少)
  • maxusage: 单个连接的最大允许复用次数(缺省值 0 或 False 代表不限制的复用)。当达到最大数值时,连接会自动重新连接(关闭和重新打开)
  • setsession: 一个可选的SQL命令列表用于准备每个会话,如 [“set datestyle to german”, …]
  • creator 函数或可以生成连接的函数可以接受这里传入的其他参数,例如主机名、数据库、用户名、密码等。你还可以选择传入creator函数的其他参数,允许失败重连和负载均衡。

python操作DBUtils:

这里话不多说,直接上代码,这里我们可以将所有配置写到一个文件里:

from DBUtils.PooledDB import PooledDB, SharedDBConnection
import pymysql
from django.http import JsonResponse

err = 'conerr'

db_config = {
        "host": "localhost",
        "port": "3306",
        "user": "xxx",
        "db": "moonkey2",
        "password": "xxxxxx",
        "charset":"utf8",
    }

spool = PooledDB(pymysql,mincached=1, maxcached=50,maxshared=50,maxconnections=50, **db_config)

def mysql_seldic(sql):
	""" 查询并返回全部数据方法(字典) """
    try:
        conn = spool.connection()
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 不对游标做任何处理就是元组
        cursor.execute(sql)
        row = cursor.fetchall()
        cursor.close()
        conn.close()
        return row
    except Exception as e:
        return err.format(error=e)



def mysql_selrowid(sql):
	"""查询并返回第一个字段数据方法(字典)"""
    try:
        conn = spool.connection()
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        rowcount = cursor.execute(sql)
        fistcol = ''
        if rowcount > 0:
            row_1 = cursor.fetchone()
            fistcol = row_1[0]
        cursor.close()
        conn.close()
        return fistcol
    except Exception as e:
        return err.format(error=e)

def mysql_insert(sql):
	"""插入新的数据"""
    try:
        conn = spool.connection()
        cursor = conn.cursor()
        effect_row = cursor.execute(sql)
        conn.commit()
        cursor.close()
        conn.close()
        return effect_row
    except Exception as e:
        return err.format(error=e)

def commit(sql):
	'''事务'''
   conn = spool.connection()
   cursor = conn.cursor()
   # uid = uuid.uuid1()
   try:
       # writetxt('sql','mysql_commit:'+ '  '  + str(datetime.datetime.now()) + '  ' +str(sql) + ' uid ' + str(uid)  )
       cursor.execute(sql)
       cursor.close()
       conn.commit()
       return 1
   except Exception as e:
       # writetxt('sql','Exception:'+ '  '  + str(datetime.datetime.now()) + '  ' +str(e)  )
       conn.rollback()
       return err
   finally:
       conn.close()

然后我们可以写调用函数去使用这些方法:

import Conn

#查询引导数据
def selguidanceinfo(guidanceinfoid):
    sql = ' select gi.type,gi.guidanceinfoname,gi.guidanceinfoid from zy_guidanceinfo gi where gi.guidanceinfoid='+ str(guidanceinfoid) +'  '
    guidanceinfo = conn.mysql_seldic(sql)
    return guidanceinfo

当然我还看到另一篇博客中用类来实例化属性的连接池,在这里记录一下:

Python实现Mysql数据库连接池

class Mysql(object):
    """
    MYSQL数据库对象,负责产生数据库连接 , 此类中的连接采用连接池实现获取连接对象:conn = Mysql.getConn()
            释放连接对象;conn.close()或del conn
    """
    #连接池对象
    __pool = None
    def __init__(self):
        #数据库构造函数,从连接池中取出连接,并生成操作游标
        self._conn = Mysql.__getConn()
        self._cursor = self._conn.cursor()
 
    @staticmethod
    def __getConn():
        """
        @summary: 静态方法,从连接池中取出连接
        @return MySQLdb.connection
        """
        if Mysql.__pool is None:
            __pool = PooledDB(creator=MySQLdb, mincached=1 , maxcached=20 ,
                              host=Config.DBHOST , port=Config.DBPORT , user=Config.DBUSER , passwd=Config.DBPWD ,
                              db=Config.DBNAME,use_unicode=False,charset=Config.DBCHAR,cursorclass=DictCursor)
        return __pool.connection()


    def getOne(self,sql,param=None):
        """
        @summary: 执行查询,并取出第一条
        @param sql:查询SQL,如果有查询条件,请只指定条件列表,并将条件值使用参数[param]传递进来
        @param param: 可选参数,条件列表值(元组/列表)
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchone()
        else:
            result = False
            

这种我用上面那个函数同样进行了查询,基本效果都一样,如果要查看详细的增删改查代码可以移步他的博客。当然,我感觉这两种都不是代码的最精简版本,还可以做进一步封装,不过如果从可读性来讲,差不多了。

猜你喜欢

转载自blog.csdn.net/submarineas/article/details/103202528
今日推荐