• 数据库连接池


    数据库连接池

    ​ 如果在开线程请求数据库中如果觉得所用时间太长的话,就可以通过python数据库连接池去改善一下在此方面的不足之处。

    python编程中可以使用pymysql进行数据库连接及增删改查操作,但每次连接mysql请求时,都是独立的去请求访问,比较浪费资源,而且访问数量达到一定数量时,对mysql的性能会产生较大的影响。因此实际使用中,通常会使用数据库的连接池技术,来访问数据库达到资源复用。

    连接池对性能的提升:

    • 在程序创建连接的时候,可以从一个空闲的连接中获取,不需要重新初始化连接,提升获取连接的速度。
    • 关闭连接的时候,把连接放回连接池,而不是真正的关闭,所以可以减少频繁的打开和关闭连接。

    python的数据库连接池包:DBUtils

    DBUtils提供两种外部接口:

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

    DBUtils包安装: pip3 install DBUtils

    ​ 或者下载 DBUtils 安装包,解压后,使用python setup.py install 命令进行安装

    未使用连接池的数据库方法:(app下database)

    定义数据库连接类

    import pymysql
    import pymysql.cursors
    from DBUtils.PooledDB import PooledDB
    
    d_host = settings.DATABASES['default']['HOST']
    d_port = settings.DATABASES['default']['PORT']
    d_user = settings.DATABASES['default']['USER']
    d_password = settings.DATABASES['default']['PASSWORD']
    d_db = settings.DATABASES['default']['NAME']
    
    class DataBase:
        host, port, user, password, database = d_host, int(d_port), d_user, d_password, d_db
    
        def __init__(self, host='', port='', user='', password='', database=''):
            if not host == '':
                self.host = host
            if not port == '':
                self.port = int(port)
            if not user == '':
                self.user = user
            if not password == '':
                self.password = password
            if not database == '':
                self.database = database
    
        def query_sql(self, sql,args=None):
            conn = pymysql.connect(host=self.host, port=self.port, user=self.user, passwd=self.password, db=self.database, charset='utf8', cursorclass=pymysql.cursors.DictCursor)
            cur = conn.cursor()  # 获得 cursor(dict形式).
            if args is None:
                cur.execute(sql)
            else:
                cur.execute(sql, args)  # 通过cursor执行SQL语句.
            result = cur.fetchall()  # 获得数据库操作返回结果.
            cur.close()
            conn.close()
            return result  # 返回查询结果.
    
        def update_sql(self, sql_str,args=None):
            conn = pymysql.connect(host=self.host, port=self.port, user=self.user, passwd=self.password, db=self.database, charset='utf8', cursorclass=pymysql.cursors.DictCursor)
            cur = conn.cursor()
            cur.execute('begin')
            if args is None:
                result = cur.execute(sql_str)
            else:
                result = cur.execute(sql_str,args)
            cur.execute('commit')
            cur.close()
            conn.close()
            return result
    
        def execute_sql(self, sql,args=None):
            conn = pymysql.connect(host=self.host, port=self.port, user=self.user, passwd=self.password, db=self.database, charset='utf8', cursorclass=pymysql.cursors.DictCursor)
            cur = conn.cursor()
            if args is None:
                cur.execute(sql)
            else:
                cur.execute(sql, args)
            conn.commit()
            result = cur.lastrowid
            cur.close()
            conn.close()
            return result
    调用方法
    
    db = database.DB()
    sql = """
        select * from course
    """
    result = db.query_sql(sql)

    用数据库连接池后的方法:

    定义数据库连接类

    import pymysql
    import pymysql.cursors
    from DBUtils.PooledDB import PooledDB
    
    d_host = settings.DATABASES['default']['HOST']
    d_port = settings.DATABASES['default']['PORT']
    d_user = settings.DATABASES['default']['USER']
    d_password = settings.DATABASES['default']['PASSWORD']
    d_db = settings.DATABASES['default']['NAME']
    
    
    PY_MYSQL_CONN_DICT = {
        "host": d_host,
        "port": int(d_port),
        "user": d_user,
        "passwd": d_password,
        "db": d_db,
        'charset': 'utf8',
    }
    
    class SQLPoll(object):
    
        # docstring for DbConnection
    
        __poll = None
    
        def __init__(self):
            self.pool = self.__get_db()
            self.conn = self.pool.connection()
            self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
    
        @classmethod
        def __get_db(cls):
            if cls.__poll is None:
                cls.__poll = PooledDB(
                    creator=pymysql,
                    mincached=10,
                    maxconnections=100,
                    **PY_MYSQL_CONN_DICT)
            return cls.__poll
    
        def fetch_all(self, sql, args=None):
            if args is None:
                self.cursor.execute(sql)
            else:
                self.cursor.execute(sql, args)
            result = self.cursor.fetchall()
            return result
    
        def fetch_one(self, sql, args=None):
            if args is None:
                self.cursor.execute(sql)
            else:
                self.cursor.execute(sql, args)
            result = self.cursor.fetchone()
            return result
    
        def execute(self, sql, args):
            self.cursor.execute(sql, args)
            self.conn.commit()
            result = self.cursor.lastrowid
            return result
    
        def __close(self):
            self.cursor.close()
            self.conn.close()
    
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.__close()

    使用方法

    sql = """select * from course where id > %s"""
    args = (10,)
    with SQLPoll() as db:
        course_list = db.fetch_all(sql,args)
    

      

    PooledDB可选参数解释:

    1. mincached,最少的空闲连接数,如果空闲连接数小于这个数,pool会创建一个新的连接。
    2. maxcached,最大的空闲连接数,如果空闲连接数大于这个数,pool会关闭空闲连接。
    3. maxconnections,最大的连接数,进程中最大可创建的线程数。
    4. blocking, 当连接数达到最大连接数时,再次请求时,如果这个值是True,请求连接的程序会一直等待,直到当前连接数小于最大连接数;如果这个值为False,会报错。
    5. masxshared,当连接数达到这个数时,新请求的连接会分享已经分配出去的连接。

    在uwsgi中,每个http请求都会有一个进程,连接池中配置的连接数都是一个进程为单位的(即上面的最大连接数,都是在一个进程中创建的线程数),如果业务中,一个http请求中需要的sql连接数不是很多的话(其实大多数都只需要创建一个连接),配置的连接数配置都不需要太大。

  • 相关阅读:
    Android开发之SQLite的使用方法
    【转】如何分析解决Android ANR
    error log
    33层高楼为什么27楼和28楼最贵 次顶层房价高原因揭秘
    Could not allocate CursorWindow size due to error -12 错误解决方法
    过来人讲述买房血泪史:什么样的房子不能碰
    cocos2d-x删除vs2010项目模板
    Lua学习笔记5:类及继承的实现
    Linux vsftpd服务配置具体解释
    Android_Dialog_设置Dialog窗体的大小
  • 原文地址:https://www.cnblogs.com/qianniao2122/p/14216297.html
Copyright © 2020-2023  润新知