當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Python Django atomic用法及代碼示例


本文介紹 django.db.transaction.atomic 的用法。

聲明

atomic(using=None, savepoint=True, durable=False)[source]

原子性是數據庫事務的定義屬性。 atomic 允許我們創建一個代碼塊,在其中保證數據庫的原子性。如果代碼塊成功完成,則將更改提交到數據庫。如果出現異常,則回滾更改。

atomic 塊可以嵌套。在這種情況下,當一個內部塊成功完成時,如果稍後在外部塊中引發異常,它的效果仍然可以回滾。

確保atomic 塊始終是最外層的atomic 塊有時很有用,以確保在退出塊時提交任何數據庫更改而沒有錯誤。這稱為持久性,可以通過設置 durable=True 來實現。如果 atomic 塊嵌套在另一個塊中,則會引發 RuntimeError

atomic 既可用作裝飾器:

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

並作為上下文管理器:

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

在 try/except 塊中包裝 atomic 允許自然處理完整性錯誤:

from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
    create_parent()

    try:
        with transaction.atomic():
            generate_relationships()
    except IntegrityError:
        handle_exception()

    add_children()

在此示例中,即使 generate_relationships() 通過破壞完整性約束導致數據庫錯誤,您也可以在 add_children() 中執行查詢,並且來自 create_parent() 的更改仍然存在並綁定到同一個事務。請注意,在調用 handle_exception() 時,在 generate_relationships() 中嘗試的任何操作都已經安全回滾,因此異常處理程序也可以在必要時對數據庫進行操作。

避免在 atomic 中捕獲異常!

當退出 atomic 塊時,Django 會查看它是正常退出還是異常退出,以確定是提交還是回滾。如果您在 atomic 塊中捕獲並處理異常,您可能會向 Django 隱藏已發生問題的事實。這可能會導致意外行為。

這主要是 DatabaseError 及其子類(例如 IntegrityError )的問題。在這樣的錯誤之後,事務被破壞,Django 將在atomic 塊的末尾執行回滾。如果您嘗試在回滾發生之前運行數據庫查詢,Django 將引發 TransactionManagementError 。當ORM-related 信號處理程序引發異常時,您也可能會遇到此行為。

捕獲數據庫錯誤的正確方法是圍繞 atomic 塊,如上所示。如有必要,為此添加一個額外的atomic 塊。這種模式還有另一個優點:它明確界定了如果發生異常,哪些操作將被回滾。

如果您捕獲原始 SQL 查詢引發的異常,則 Django 的行為是未指定的並且database-dependent。

回滾事務時,您可能需要手動恢複模型狀態。

當事務回滾發生時,模型字段的值不會被恢複。除非您手動恢複原始字段值,否則這可能會導致模型狀態不一致。

例如,給定帶有 active 字段的 MyModel,如果在事務中將 active 更新為 True 失敗,則此代碼段可確保最後的 if obj.active 檢查使用正確的值:

from django.db import DatabaseError, transaction

obj = MyModel(active=False)
obj.active = True
try:
    with transaction.atomic():
        obj.save()
except DatabaseError:
    obj.active = False

if obj.active:
    ...

為了保證原子性,atomic 禁用了一些 API。嘗試在 atomic 塊內提交、回滾或更改數據庫連接的自動提交狀態將引發異常。

atomic 采用 using 參數,該參數應該是數據庫的名稱。如果沒有提供這個參數,Django 使用 "default" 數據庫。

在底層,Django 的事務管理代碼:

  • 進入最外層atomic塊時打開一個事務;
  • 進入內部atomic 塊時創建保存點;
  • 退出內部塊時釋放或回滾到保存點;
  • 退出最外層塊時提交或回滾事務。

您可以通過將 savepoint 參數設置為 False 來禁用為內部塊創建保存點。如果發生異常,Django 將在退出第一個帶有保存點的父塊時執行回滾,如果有,則退出最外層的塊。原子性仍然由外部事務保證。僅當保存點的開銷很明顯時才應使用此選項。它的缺點是破壞了上述錯誤處理。

當自動提交關閉時,您可以使用atomic。它隻會使用保存點,即使是最外麵的塊。

相關用法


注:本文由純淨天空篩選整理自djangoproject.com大神的英文原創作品 django.db.transaction.atomic。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。