這更像是一個設計問題。
直到最近,我一直在我的開發環境中使用 Django 和 SQLite,但我現在已經更改為 PostgreSQL 進行生產。我的應用程式是使用 Heroku 部署的,幾天后我意識到他們對資料庫進行了隨機維護,幾分鐘后它就崩潰了。
例如,有一個包含 3 個表的模型,Procedure每個表都指向 a ProcedureList,而 aProcedureList可以有多個Procedure。AProcedureUser將 aProcedureList和用戶鏈接起來,并為用戶設定一些特定的變數ProcedureList。最后有一個ProcedureState將 aProcedure與特定用戶的狀態相關聯。
在我的應用程式中,在其中一個視圖中,我有一個以以下方式修改資料庫的函式:
user = request.user
plist = ProcedureList.objects.get(id=idFromUrl)
procedures = Procedure.objects.filter(ProcedureList=pList)
pUser = ProcedureUser(plist, user, someVariables)
pUser.save()
for procedure in procedures:
pState = ProcedureState(plist, user, pUser, procedure, otherVariables)
pState.save()
所以我現在想的是,如果 Heroku 決定在這些object.save()呼叫之間進行維護,我們就會遇到問題。以后的呼叫.save()將失敗,資料庫將被損壞。用戶的請求當然會失敗,并且無法回滾之前的插入,因為無法與資料庫連接。
我的問題是,如果資料庫失敗(由 Heroku 維護、網路錯誤或其他原因給出),我們應該如何正確回滾資料庫?我們是否應該制作一個插入串列并等待 DB 再次上升以將它們回滾?
我正在使用 Python 3 和 Django 4,但我認為這是一個普遍的問題,而不是特定于任何平臺的問題。
uj5u.com熱心網友回復:
如果資料庫失敗(由于 Heroku 維護、網路錯誤或其他原因),我們應該如何正確回滾資料庫?
資料庫通過原子事務 [wiki]解決了這個問題。原子事務是一組提交all或none的查詢。因此,對于此類事務,不可能應用某些查詢而其他查詢不應用。
Django 提供了一個transaction 背景關系管理器 [Django-doc]來在事務中執行作業:
from django.db import transaction
with transaction.atomic():
user = request.user
plist = ProcedureList.objects.get(id=idFromUrl)
procedures = Procedure.objects.filter(ProcedureList=pList)
pUser = ProcedureUser(plist, user, someVariables)
pUser.save()
ProcedureState.objects.bulk_create([
ProcedureState(plist, user, pUser, procedure, otherVariables)
for procedure in procedures
])
在背景關系塊的末尾,它將提交更改。這意味著如果資料庫在兩者之間發生故障,則不會提交操作,并且該塊將引發例外(通常是IntegrityError)。
注意:Django 有一個
.bulk_create(…)方法 [Django-doc]可以使用單個資料庫查詢創建多個專案,從而最大限度地減少資料庫和應用程式層之間的帶寬。這通常會勝過在回圈中創建專案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/442559.html
