1. 程式人生 > >Flask之數據庫連接池DBuilt

Flask之數據庫連接池DBuilt

cache creat 檢查 eve dbutil share roo 當前 import

DBUtils是Python的一個用於實現數據庫連接池的模塊。

如果沒有連接池,使用pymysql來連接數據庫時,單線程應用完全沒有問題,但如果涉及到多線程應用那麽就需要加鎖,一旦加鎖那麽連接勢必就會排隊等待,當請求比較多時,性能就會降低了。

加鎖:

技術分享圖片
 1 import pymysql
 2 import threading
 3 from threading import RLock
 4 
 5 LOCK = RLock()
 6 CONN = pymysql.connect(host=127.0.0.1,
 7                        port=3306,
 8                        user=
root, 9 password=123, 10 database=pooldb, 11 charset=utf8) 12 13 14 def task(arg): 15 with LOCK: 16 cursor = CONN.cursor() 17 cursor.execute(select * from tb1) 18 result = cursor.fetchall() 19
cursor.close() 20 21 print(result) 22 23 24 for i in range(10): 25 t = threading.Thread(target=task, args=(i,)) 26 t.start()
View Code

不加鎖:

技術分享圖片
 1 import pymysql
 2 import threading
 3 CONN = pymysql.connect(host=127.0.0.1,
 4                        port=3306,
 5                        user=
root, 6 password=123, 7 database=pooldb, 8 charset=utf8) 9 10 11 def task(arg): 12 cursor = CONN.cursor() 13 cursor.execute(select * from tb1) 14 result = cursor.fetchall() 15 cursor.close() 16 17 print(result) 18 19 20 for i in range(10): 21 t = threading.Thread(target=task, args=(i,)) 22 t.start()
View Code

此連接池有兩種連接模式:

模式一:為每個線程創建一個連接,線程即使調用了close方法,也不會關閉,只是把連接重新放到連接池,供自己線程再次使用。當線程終止時,連接自動關閉

技術分享圖片
 1 POOL = PersistentDB(
 2     creator=pymysql,  # 使用鏈接數據庫的模塊
 3     maxusage=None,  # 一個鏈接最多被重復使用的次數,None表示無限制
 4     setsession=[],  # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."]
 5     ping=0,
 6     # 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
 7     closeable=False,
 8     # 如果為False時, conn.close() 實際上被忽略,供下次使用,再線程關閉時,才會自動關閉鏈接。如果為True時, conn.close()則關閉鏈接,那麽再次調用pool.connection時就會報錯,因為已經真的關閉了連接(pool.steady_connection()可以獲取一個新的鏈接)
 9     threadlocal=None,  # 本線程獨享值得對象,用於保存鏈接對象,如果鏈接對象被重置
10     host=127.0.0.1,
11     port=3306,
12     user=root,
13     password=123,
14     database=pooldb,
15     charset=utf8
16 )
17 
18 def func():
19     conn = POOL.connection(shareable=False)
20     cursor = conn.cursor()
21     cursor.execute(select * from tb1)
22     result = cursor.fetchall()
23     cursor.close()
24     conn.close()
25 
26 func()
View Code

模式二:創建一批連接到連接池,供所有線程共享使用。
PS:由於pymysql、MySQLdb等threadsafety值為1,所以該模式連接池中的線程會被所有線程共享。

技術分享圖片
 1 import time
 2 import pymysql
 3 import threading
 4 from DBUtils.PooledDB import PooledDB, SharedDBConnection
 5 POOL = PooledDB(
 6     creator=pymysql,  # 使用鏈接數據庫的模塊
 7     maxconnections=6,  # 連接池允許的最大連接數,0和None表示不限制連接數
 8     mincached=2,  # 初始化時,鏈接池中至少創建的空閑的鏈接,0表示不創建
 9     maxcached=5,  # 鏈接池中最多閑置的鏈接,0和None不限制
10     maxshared=3,  # 鏈接池中最多共享的鏈接數量,0和None表示全部共享。PS: 無用,因為pymysql和MySQLdb等模塊的 threadsafety都為1,所有值無論設置為多少,_maxcached永遠為0,所以永遠是所有鏈接都共享。
11     blocking=True,  # 連接池中如果沒有可用連接後,是否阻塞等待。True,等待;False,不等待然後報錯
12     maxusage=None,  # 一個鏈接最多被重復使用的次數,None表示無限制
13     setsession=[],  # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."]
14     ping=0,
15     # 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
16     host=127.0.0.1,
17     port=3306,
18     user=root,
19     password=123,
20     database=pooldb,
21     charset=utf8
22 )
23 
24 
25 def func():
26     # 檢測當前正在運行連接數的是否小於最大鏈接數,如果不小於則:等待或報raise TooManyConnections異常
27     # 否則
28     # 則優先去初始化時創建的鏈接中獲取鏈接 SteadyDBConnection。
29     # 然後將SteadyDBConnection對象封裝到PooledDedicatedDBConnection中並返回。
30     # 如果最開始創建的鏈接沒有鏈接,則去創建一個SteadyDBConnection對象,再封裝到PooledDedicatedDBConnection中並返回。
31     # 一旦關閉鏈接後,連接就返回到連接池讓後續線程繼續使用。
32     conn = POOL.connection()
33 
34     # print(th, ‘鏈接被拿走了‘, conn1._con)
35     # print(th, ‘池子裏目前有‘, pool._idle_cache, ‘\r\n‘)
36 
37     cursor = conn.cursor()
38     cursor.execute(select * from tb1)
39     result = cursor.fetchall()
40     conn.close()
41 
42 
43 func()
View Code

Flask之數據庫連接池DBuilt