博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么要使用数据库连接池?以及用法(DBUtils)
阅读量:6498 次
发布时间:2019-06-24

本文共 4759 字,大约阅读时间需要 15 分钟。

看代码,

from flask import Flaskfrom db import POOLimport pymysqlapp = Flask(__name__)app.secret_key ='sdfsdfsdf'@app.route('/index')def index():    # 第一步:缺点:每次请求反复创建数据库连接,连接数太多。    # conn = pymysql.connect()    # cursor = conn.cursor()    # cursor.execute('select * from tb where id > %s',[5,])    # result = cursor.fetchall()    # cursor.close()    # conn.close()    # print(result)

对于这种方式,每来一个用户请求,都要去创建一个链接。对于数据库来说,过分了。可并发,但是连接数太多。

就算你改成在全局创建,只用一个链接,但是会变成串行。

如果是多线程的话,这样的方式是不是会报错哦?pymysql它同一时间只能处理一个线程。

那来,我们这样玩,还是在将链接操作放在全局。

# 第二步:缺点,不能支持并发    # pymysql.threadsafety    # with LOCK:    #     cursor = CONN.cursor()    #     cursor.execute('select * from tb where id > %s', [5, ])    #     result = cursor.fetchall()    #     cursor.close()    #    #     print(result)

加把锁。这样支持多线程了吧?

可是。。。 它支持并发吗? 并不支持

 

 

让它俩折中一下,这样来玩。

  基于DBUtils实现数据链接池。

    模式一:每个线程独立创建自己的链接,无论该线程使用多少次,用的都是同一个。该线程关闭时,伪关闭,本地线程再次调用时,继续使用最开始创建的链接。

        何时关闭? 线程不终止,永不关闭!所有线程终止数据库连接,该线程关闭。

    模式二:多线程间不分彼此。 创建一个连接池(此处才体现出池),为所有线程提供链接。

        使用时从池里获取,使用完毕后,放回连接池。    

        拿的时候,pop出来,用完再append进去。

        连接池里的连接,排队依次被使用。

          补充:共享时,可设置最多共享数???

              文档里写的可以设置最大共享数,比如我池里有10个线程,最大共享数设置5,你是否认为最多5个可以被来回玩?

                NO!源码里面,清清楚楚的写到:大家都是朋友,不见外,一起玩。

                pymsql里面的threadsafety=1,代表:无论你如何使用,所有连接都可被重复使用。

 

本地线程示例:保证每个线程都有数据库连接,都持有自己的一份数据,在操作时,不会相互影响。

import threadingimport time# 本地线程对象local_values = threading.local()def func(num):    """    # 第一个线程进来,本地线程对象会为他创建一个    # 第二个线程进来,本地线程对象会为他创建一个    :param num:     :return:     """    local_values.name = num # 4    # 线程停下来了    time.sleep(2)    print(local_values.name, threading.current_thread().name)for i in range(5):    th = threading.Thread(target=func, args=(i,), name='线程%s' % i)    th.start()
local

 

模式二示例:

import timeimport pymysqlimport threadingfrom DBUtils.PooledDB import PooledDB, SharedDBConnectionPOOL = PooledDB(    creator=pymysql,  # 使用链接数据库的模块    maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数    mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建    maxcached=5,  # 链接池中最多闲置的链接,0和None不限制    maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。    blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错    maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制    setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]    ping=0,    # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always    host='127.0.0.1',    port=3306,    user='root',    password='123',    database='pooldb',    charset='utf8')def func():    # 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常    # 否则    # 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。    # 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。    # 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。    # 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。    # PooledDedicatedDBConnection    conn = POOL.connection()    # print(th, '链接被拿走了', conn1._con)    # print(th, '池子里目前有', pool._idle_cache, '\r\n')    cursor = conn.cursor()    cursor.execute('select * from tb1')    result = cursor.fetchall()    conn.close()    conn = POOL.connection()    # print(th, '链接被拿走了', conn1._con)    # print(th, '池子里目前有', pool._idle_cache, '\r\n')    cursor = conn.cursor()    cursor.execute('select * from tb1')    result = cursor.fetchall()    conn.close()func()
PooledDB

 

模式二连接池用法:

import timeimport pymysqlimport threadingfrom DBUtils.PooledDB import PooledDB, SharedDBConnectionPOOL = PooledDB(    creator=pymysql,  # 使用链接数据库的模块    maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数    mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建    maxcached=5,  # 链接池中最多闲置的链接,0和None不限制    maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。    blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错    maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制    setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]    ping=0,    # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always    host='127.0.0.1',    port=3306,    user='root',    password='123',    database='pooldb',    charset='utf8')
from flask import Flaskfrom db import POOLimport pymysqlapp = Flask(__name__)app.secret_key ='sdfsdfsdf'@app.route('/index')def index():    conn = POOL.connection()    cursor = conn.cursor()    cursor.execute('select * from tb1')    result = cursor.fetchall()    conn.close()    return '执行成功'if __name__ == '__main__':    # app.__call__    app.run()

 

转载于:https://www.cnblogs.com/ugfly/p/8254499.html

你可能感兴趣的文章
datatable无法设置横向滚动条(设置无效)
查看>>
扩展欧几里德
查看>>
LC_83. Remove Duplicates from Sorted List
查看>>
NYOJ 576 集齐卡片赢大奖(一)
查看>>
Java基础 - 面向对象 - 构造方法
查看>>
234. Palindrome Linked List - Easy
查看>>
undefined symbol: ap_log_rerror;apache2.4与weblogic点so文件
查看>>
查看sqlserver被锁的表以及如何解锁
查看>>
x多进程
查看>>
06、ActivationDeactivation
查看>>
runtime实践之Method Swizzling
查看>>
Day03 - Ruby比一比:Module的include与extend
查看>>
Treap
查看>>
SQL优化快速入门
查看>>
项目管理深入理解08--成本管理
查看>>
Google Analytics功能篇 - 如何跟踪邮件打开率与点击率
查看>>
Code Lock
查看>>
nginx学习之静态内容篇(五)
查看>>
19.04.02笔记
查看>>
vim常用命令总结 (转)
查看>>