資料庫連線池(DBUtils)
阿新 • • 發佈:2018-12-08
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