1. 程式人生 > >資料庫連線池(DBUtils)

資料庫連線池(DBUtils)

DButils是python的一個實現資料庫連線池的模組

  兩種模式:

  1.為每一個執行緒建立一個連結,即使執行緒即使呼叫了close()方法,也不會關閉,只是把執行緒放到連線池,供自己再次使用,當連線關閉時,執行緒連線自動關閉。

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 = '127.0.0.1', port = 3306, user = 'root', password = 'xxx', database = 'xxx', charset = '
utf8' ) def func(): conn = PooL.connection() cursor = conn.cursor() cursor.execute('select * from book') result = cursor.fetchall() print(result) cursor.close() conn.close() import threading for i in range(5): t = threading.Thread(target=func) t.start()

2.建立一批連線到連線池,供所有執行緒共享使用

  注意:由於pymysql,mysqlDB中的threadsafety值為1,所有執行緒共享連線

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',
    password = 'xxx',
    database = 'xxx',
    charset = 'utf8'
)
def func():
    #檢測當前正在執行的連線數是否小於最大的連線數,如果不小於則等待連線或者丟擲raise TooManyConnections異常
    #否則優先去初始化時建立的連線中獲取連線SteadyDBConnection
    #然後將SteadyDBConnection物件封裝到PooledDedicatedDBConnection中並返回
    #如果最開始建立的連線沒有連結,則去建立SteadyDBConnection物件,再封裝到PooledDedicatedDBConnection中並返回
    #一旦關閉連結後,連線就返回到連線池讓後續執行緒繼續使用
    conn = POOL.connection()
    cursor = conn.cursor()
    cursor.execute('select * from book')
    result = cursor.fetchall()
    print(result)
    conn.close()
func()

PS:關於pymysql模組,如果沒有單執行緒的情況,連線MySQL資料庫沒有問題,但如果要是多執行緒,就需要加鎖,一旦加鎖,後面的執行緒就得等待,勢必會降低使用效率。

加鎖
import
pymysql import threading from threading import RLock LOCK = RLock() CONN = pymysql.connect(host='127.0.0.1', port = 3306, user = 'root', password = 'xxx', database = 'xxx', charset = 'utf8' ) def task(arg): with LOCK: cursor = CONN.cursor() cursor.execute('select * from book') result = cursor.fetchall() cursor.close() print(result) for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
不加鎖
import pymysql
import threading
CONN = pymysql.connect(host='127.0.0.1',
                       port=3306,
                       user='root',
                       password='xxx',
                       database='ok1',
                       charset='utf8')

def task(arg):
    cursor = CONN.cursor()
    cursor.execute('select * from book')
    result = cursor.fetchall()
    cursor.close()
    print(result)
for i in range(10):  #1時不會報錯
    t = threading.Thread(target=task, args=(i,))
    t.start()

 

自定義helper,使用模式2連線池操作資料庫

import pymysql


def connect(): conn = POOL.connection() cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 結果為字典 return conn,cursor def connect_close(conn,cursor): cursor.close() conn.close() def fetch_all(sql,args): conn,cursor = connect() cursor.execute(sql, args) record_list = cursor.fetchall() connect_close(conn,cursor) return record_list def fetch_one(sql, args): conn, cursor = connect() cursor.execute(sql, args) result = cursor.fetchone() connect_close(conn, cursor) return result def insert(sql, args): conn, cursor = connect() row = cursor.execute(sql, args) conn.commit() connect_close(conn, cursor) return row