django 數(shù)據(jù)庫(kù)連接模塊解析及簡(jiǎn)單長(zhǎng)連接改造方法
工作中純服務(wù)端的項(xiàng)目用到了線(xiàn)程池和django的ORM部分。django 的數(shù)據(jù)庫(kù)連接在每一個(gè)線(xiàn)程中開(kāi)啟一份,并在查詢(xún)完畢后自動(dòng)關(guān)閉連接。
線(xiàn)程池處理任務(wù)時(shí),正常使用的連接中不會(huì)被關(guān)閉,但由于數(shù)據(jù)庫(kù)端有最長(zhǎng)連接時(shí)間的限制(默認(rèn)為8小時(shí)),在超時(shí)后會(huì)發(fā)生InterfaceError: (0, '')(連接關(guān)閉后使用連接/游標(biāo))或Error(2006, 'MySQL server has gone away')(mysql 服務(wù)器主動(dòng)關(guān)閉連接)這類(lèi)錯(cuò)誤,所以一般會(huì)在每個(gè)任務(wù)線(xiàn)程中調(diào)用django.db.connection.close()進(jìn)行關(guān)閉操作。
但對(duì)于頻繁進(jìn)行數(shù)據(jù)庫(kù)連接并操作數(shù)據(jù)庫(kù)的業(yè)務(wù),反復(fù)創(chuàng)建連接并不是好的選擇,這種場(chǎng)景下可以考慮將連接改造為長(zhǎng)連接。
1. django 代碼的閱讀筆記
django.db.__init__.py #對(duì)象: connections = ConnectionHandler() connection = DefaultConnectionProxy() # 函數(shù) # 重置查詢(xún)記錄緩存 def reset_queries(**kwargs): pass # 關(guān)閉不可用或超時(shí)(如果有設(shè)置 CONN_MAX_AGE)連接 def close_old_connections(**kwargs): pass # 信號(hào) # 在請(qǐng)求開(kāi)始或完成時(shí)自動(dòng)調(diào)用相應(yīng)處理函數(shù) signals.request_started.connect(reset_queries) signals.request_started.connect(close_old_connections) signals.request_finished.connect(close_old_connections)
重點(diǎn)是connections和connection兩個(gè)實(shí)例
connections 是 ConnectionHandler類(lèi)
connections.all()會(huì)給出一個(gè)列表,里面的元素為DatabaseWrapper類(lèi)
ConnectionHandler內(nèi)置對(duì)象及連接管理:
def __init__(): self._connections = local() # 連接包裝類(lèi)里的連接是根據(jù)配置情況使用相應(yīng)的連接 def __getitem__(self, alias): '''略''' db = self.databases[alias] backend = load_backend(db['ENGINE']) conn = backend.DatabaseWrapper(db, alias) setattr(self._connections, alias, conn) # 返回所管理的數(shù)據(jù)庫(kù)連接 # 管理方式:分?jǐn)?shù)據(jù)庫(kù),線(xiàn)程管理連接 def all(self): return [self[alias] for alias in self] # 關(guān)閉所有數(shù)據(jù)庫(kù)連接 def close_all(self): for alias in self: try: connection = getattr(self._connections, alias) except AttributeError: continue connection.close()
threading.local 是一個(gè)全局變量,local的屬性是非線(xiàn)程共享的,也就是在每一個(gè)線(xiàn)程中都會(huì)有單獨(dú)一個(gè)數(shù)據(jù)庫(kù)連接實(shí)例創(chuàng)建,因?yàn)榇砑鞍b的原因,該連接實(shí)例為對(duì)應(yīng)backend里的連接(比如,pymysql.connections.Connection)。
在線(xiàn)程池的情況下,close_old_connections方法是不能將線(xiàn)程中的數(shù)據(jù)庫(kù)連接關(guān)閉的。
connection是DefaultConnectionProxy類(lèi)的實(shí)例,實(shí)際是DatabaseWrapper的實(shí)例 (使用了pymysql庫(kù):import pymysql; pymysql.install_as_MySQLdb) DefaultConnectionProxy–>DatabaseWrapper–>pymysql.connections.Connection(根據(jù)connections的處理調(diào)用相應(yīng)的數(shù)據(jù)庫(kù)連接包) connection有幾個(gè)關(guān)鍵方法和屬性 connection.connection = '被包裝的pymysql.connections.Connection實(shí)例` connection.close_at = None if max_age is None else time.time() + max_age # 設(shè)置的連接關(guān)閉時(shí)間 connection.connect()# 獲取連接 connection.cursor() # 獲取游標(biāo) connection.close()# 關(guān)閉連接
2. 將數(shù)據(jù)庫(kù)連接改造為長(zhǎng)連接
max_age(CONN_MAX_AGE) 是可以在settings里面配置的。
由于多個(gè)服務(wù)共用一套配置, 所以考慮直接在程序里修改
全局變量
max_age = 7 * 3600
在線(xiàn)程內(nèi)開(kāi)始時(shí)做下判斷:
if not db.connection.connection or db.connection.close_at < time.time(): db.connection.close() db.connection.connect() db.connection.close_at = time.time() + max_age print "A new conn creates !" else: print "Still old conn!"
這樣每個(gè)線(xiàn)程池中的線(xiàn)程會(huì)循環(huán)執(zhí)行任務(wù)并只使用同一個(gè)連接,并可以控制在自己需要的連接時(shí)長(zhǎng)后更換連接。
針對(duì)線(xiàn)程池的情況,close_old_connections基本沒(méi)啥用處, 可以跳過(guò)該處理
django.db.close_old_connections = lambda **kwargs : None
以上這篇django 數(shù)據(jù)庫(kù)連接模塊解析及簡(jiǎn)單長(zhǎng)連接改造方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python爬蟲(chóng)之Selenium中frame/iframe表單嵌套頁(yè)面
這篇文章主要介紹了Python爬蟲(chóng)之Selenium中frame/iframe表單嵌套頁(yè)面,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
使用tensorflow根據(jù)輸入更改tensor shape
這篇文章主要介紹了使用tensorflow根據(jù)輸入更改tensor shape,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
pandas數(shù)值排序的實(shí)現(xiàn)實(shí)例
篩選和排序是Excel中使用頻率最多的功能,本文主要介紹了pandas數(shù)值排序的實(shí)現(xiàn)實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),,感興趣的可以了解一下2021-07-07
基于python實(shí)現(xiàn)分析識(shí)別文章/內(nèi)容中的高頻詞和關(guān)鍵詞
要分析一篇文章的高頻詞和關(guān)鍵詞,可以使用 Python 中的 nltk 庫(kù)和 collections 庫(kù)或者jieba庫(kù)來(lái)實(shí)現(xiàn),本篇文章介紹基于兩種庫(kù)分別實(shí)現(xiàn)分析內(nèi)容中的高頻詞和關(guān)鍵詞,需要的朋友可以參考下2023-09-09
Python+OpenCV實(shí)現(xiàn)分水嶺分割算法的示例代碼
分水嶺算法是用于分割的經(jīng)典算法,在提取圖像中粘連或重疊的對(duì)象時(shí)特別有用。本文將用Python+OpenCV實(shí)現(xiàn)這一算法,需要的可以參考一下2022-08-08
python讀取文件夾中圖片的圖片名并寫(xiě)入excel表格
這篇文章介紹了使用python讀取文件夾中圖片的圖片名并寫(xiě)入excel表格的方法。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
Pycharm連接遠(yuǎn)程mysql報(bào)錯(cuò)的實(shí)現(xiàn)
本文主要介紹了Pycharm連接遠(yuǎn)程mysql報(bào)錯(cuò)的實(shí)現(xiàn),文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08

