Django 自定義裝飾器解決MySQL server has gone away錯誤
by:授客 QQ:1033553122
測驗環境
Win 10
Python 3.5.4
Django-2.0.13.tar.gz
官方下載地址:
https://www.djangoproject.com/download/2.0.13/tarball/
問題描述
實際專案開發中,撰寫定時任務,通過Django自帶的orm去操作資料庫,發現某次執行程式報錯:
MySQL server has gone away
原因分析
mysql資料庫存在超時關閉非活動狀態連接的機制,導致Django獲取的連接失效,但是Django自身并不知道,當我們在前端通過api、web頁面發送request,Django處理request時會發送Signals,進而觸發連接狀態檢查,自動關閉不可用連接,又因為不存在可用連接的情況下,Django會自動重新創建資料庫連接,執行我們想要的操作,所以一般情況不會報這個錯誤,但是當我們使用定時任務,直接使用orm去操作資料庫時并不會觸發發送Signals的操作,拿著失效連接去操作資料庫,然后就報錯了
參考鏈接:
https://docs.djangoproject.com/en/1.8/ref/signals/#module-django.db.models.signals
解決方法
自定義關閉不可用連接裝飾器,在操作資料庫之前進行關閉不可用連接操作,
撰寫裝飾器代碼
撰寫實作代碼前,我們先看下Django相關原始碼
Django-2.0.13\django\db\__init__.py
...略
# Register an event to reset saved queries when a Django request is started.
def reset_queries(**kwargs):
for conn in connections.all():
conn.queries_log.clear()
signals.request_started.connect(reset_queries)
# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
for conn in connections.all():
conn.close_if_unusable_or_obsolete()
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)
如上英文注釋,可知道,開始請求和完成請求都會呼叫close_old_connections,重置會話事務狀態,關閉超過生命周期的連接,所以我們可以參照這個實作自己的裝飾器
新建wrappers.py
本例中,wrappers.py存放路徑:TMP/backend/common/wrappers.py(這里TMP是我的專案名稱,backend為新建應用名稱)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
'''
自定義裝飾器
'''
from django.db import close_old_connections
def close_old_database_connections(func):
'''自定義decorator,用來裝飾使用資料庫操作函式'''
def wrapper(*args, **kwargs):
close_old_connections()
return func(*args, **kwargs)
return wrapper
使用裝飾器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
from backend.common.wrappers import close_old_database_connections
@close_old_database_connections
def gather_zengtao_group_defect_trend_data():
# ...Django orm資料庫操作
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/49470.html
標籤:Python
