python的數據庫鏈接池實現----DBUtilspython
DBUtils 屬於WebWare項目的數據庫鏈接池實現模塊,用於對數據庫鏈接線程化,使能夠安全和有效的訪問數據庫的模塊數據庫
全局的DB-API 2變量 | |
---|---|
SteadyDB.py | 用於穩定數據庫鏈接 |
PooledDB.py | 鏈接池 |
PersistentDB.py | 維持持續的數據庫鏈接 |
SimplePooledDB.py | 簡單鏈接池 |
典型的 PyGreSQL 變量 | |
---|---|
SteadyPg.py | 穩定PyGreSQL鏈接 |
PooledPg.py | PyGreSQL鏈接池 |
PersistentPg.py | 維持持續的PyGreSQL鏈接 |
SimplePooledPg.py | 簡單的PyGreSQL鏈接池 |
對標準DB-API 2模塊的依賴以下圖所示:緩存
對典型的PyGreSQL模塊依賴以下圖所示:安全
DBUtils.SimplePooledDB 是一個很是簡單的數據庫鏈接池實現。他比完善的 PooledDB 模塊缺乏不少功能。 DBUtils.SimplePooledDB 本質上相似於 MiscUtils.DBPool 這個Webware的組成部分。你能夠把它看做一種演示程序。session
DBUtils.SteadyDB 是一個模塊實現了"強硬"的數據庫鏈接,基於DB-API 2創建的原始鏈接。一個"強硬"的鏈接意味着在鏈接關閉以後,或者使用次數操做限制時會從新鏈接。多線程
一個典型的例子是數據庫重啓時,而你的程序仍然在運行並須要訪問數據庫,或者當你的程序鏈接了一個防火牆後面的遠程數據庫,而防火牆重啓時丟失了狀態時。負載均衡
通常來講你不須要直接使用 SteadyDB 它只是給接下來的兩個模塊提供基本服務, PersistentDB 和 PooledDB 。函數
DBUtils.PersistentDB 實現了強硬的、線程安全的、頑固的數據庫鏈接,使用DB-API 2模塊。以下圖展現了使用 PersistentDB 時的鏈接層步驟:性能
當一個線程首次打開一個數據庫鏈接時,一個鏈接會打開並僅供這個線程使用。當線程關閉鏈接時,鏈接仍然持續打開供這個線程下次請求時使用這個已經打開的鏈接。鏈接在線程死亡時自動關閉。fetch
簡單的來講 PersistentDB 嘗試重用數據庫鏈接來提升線程化程序的數據庫訪問性能,而且他確保鏈接不會被線程之間共享。
所以, PersistentDB 能夠在底層DB-API模塊並不是線程安全的時候一樣工做的很好,而且他會在其餘線程改變數據庫會話或者使用多語句事務時一樣避免問題的發生。
DBUtils.PooledDB 實現了一個強硬的、線程安全的、有緩存的、可複用的數據庫鏈接,使用任何DB-API 2模塊。以下圖展現了使用 PooledDB 時的工做流程:
如圖所示 PooledDB 能夠在不一樣線程之間共享打開的數據庫鏈接。這在你鏈接並指定 maxshared 參數,而且底層的DB-API 2接口是線程安全才能夠,可是你仍然可使用專用數據庫鏈接而不在線程之間共享鏈接。除了共享鏈接之外,還能夠設立一個至少 mincached 的鏈接池,而且最多容許使用 maxcached 個鏈接,這能夠同時用於專用和共享鏈接池。當一個線程關閉了一個非共享鏈接,則會返還到空閒鏈接池中等待下次使用。
若是底層DB-API模塊是非線程安全的,線程鎖會確保使用 PooledDB 是線程安全的。因此你並不須要爲此擔憂,可是你在使用專用鏈接來改變數據庫會話或執行多命令事務時必須當心。
PersistentDB 和 PooledDB 都是爲了重用數據庫鏈接來提升性能,並保持數據庫的穩定性。
因此選擇何種模塊,能夠參考上面的解釋。 PersistentDB 將會保持必定數量的鏈接供頻繁使用。在這種狀況下你老是保持固定數量的鏈接。若是你的程序頻繁的啓動和關閉線程,最好使用 PooledDB 。後面將會提到更好的調整,尤爲在使用線程安全的DB-API 2模塊時。
固然,這兩個模塊的接口是很類似的,你能夠方便的在他們之間轉換,並查看哪一個更好一些。
全部模塊的使用方法都很類似,可是在初始化 "Pooled" 和 "Persistent" 時還有有些不一樣,尤爲是DB-API和PyGreSQL之間。
這裏只講解 PersistentDB 和更復雜的 PooledDB 模塊。其餘模塊的細節請參與其文檔。使用Python解釋器控制檯,你能夠顯示 PooledDB 的文檔,以下:
help(PooledDB)
爲了使用 PersistentDB 你首先須要經過建立 PersistentDB 的實例來設置一個特定數據庫鏈接的生成器,牀底以下參數:
舉個例子,若是你正在使用 pgdb 做爲數據庫模塊並想要鏈接本機數據庫 mydb ,容許重用1000次:
import pgdb # import used DB-API 2 module from DBUtils.PersistentDB import PersistentDB persist = PersistentDB(pgdb, 1000, database='mydb')
按照如上設置完成了鏈接生成器以後,你能夠按照以下來請求一個鏈接:
db = persist.connection()
你可使用這些鏈接就像使用原始的DB-API 2鏈接同樣。實際上你獲得的是一個經過``SteadyDB``獲得的強硬的鏈接,基於DB-API 2。
關閉一個強硬的鏈接使用 db.close() ,這在內部實際上被忽略掉了,而且供下次使用。在線程關閉時,也會自動關閉數據庫鏈接。你能夠改變這個行爲經過 persist._closeable 爲 True 。
爲了使用 PooledDB 模塊,你首先須要經過建立 PooledDB 來設置數據庫鏈接池,傳遞以下參數:
舉個例子,若是你正在使用 pgdb 做爲DB-API模塊,並但願鏈接池中至少有5個鏈接到數據庫 mydb
import pgdb # import used DB-API 2 module from DBUtils.PooledDB import PooledDB pool = PooledDB(pgdb, 5, database='mydb')
一旦設置好了鏈接池,你就能夠按照以下請求一個鏈接:
db = pool.connection()
你可使用這些鏈接有如原始的DB-API 2同樣。而實際使用的是``SteadyDB``版本的強硬鏈接。
請注意鏈接能夠與其餘線程共享,只要你設置 maxshared 參數爲非零,而且DB-API 2模塊也容許。若是你想要使用專用鏈接則使用:
db = pool.connection(0)
若是你再也不須要這個鏈接了,則能夠返回給鏈接池使用 db.close() 。你也可使用相同的方法獲取另外一個鏈接。
警告: 在一個多線程環境,不要使用下面的方法:
pool.connection().cursor().execute(...)
這將會致使過早的釋放鏈接以供複用,並且若是是非線程安全還會出錯。確保鏈接對象在你的使用過程當中是一直存在的,例如:
db = pool.connection() cur = db.cursor() cur.execute(...) res = cur.fetchone() cur.close() # or del cur db.close() # or del db