Django4.0 數(shù)據(jù)庫事務(wù)-底層API

2022-03-16 17:38 更新

自動(dòng)提交

Django 在 ?django.db.transaction? 模塊中提供了一個(gè) API 來管理每個(gè)數(shù)據(jù)庫連接的自動(dòng)提交狀態(tài)。

get_autocommit(using=None)

set_autocommit(autocommit, using=None)

這些函數(shù)使接受一個(gè) ?using ?參數(shù)表示所要操作的數(shù)據(jù)庫。如果未提供,則 Django 使用 "?default?" 數(shù)據(jù)庫。
自動(dòng)提交默認(rèn)為開啟,如果你將它關(guān)閉,自己承擔(dān)后果。
一旦你關(guān)閉了自動(dòng)提交, Django 將無法幫助你,數(shù)據(jù)庫將會(huì)按照你使用的數(shù)據(jù)庫適配器的默認(rèn)行為進(jìn)行操作。
在關(guān)閉自動(dòng)提交之前,你必須確保當(dāng)前沒有活動(dòng)的事務(wù),通常你可以執(zhí)行 ?commit()? 或者 ?rollback()? 函數(shù)以達(dá)到該條件。
當(dāng)一個(gè)原子 ?atomic()? 事務(wù)處于活動(dòng)狀態(tài)時(shí), Django 將會(huì)拒絕關(guān)閉自動(dòng)提交的請求,因?yàn)檫@樣會(huì)破壞原子性。

事務(wù)

事務(wù)是指具有原子性的一系列數(shù)據(jù)庫操作。即使你的程序崩潰,數(shù)據(jù)庫也會(huì)確保這些操作要么全部完成要么全部都未執(zhí)行。

Django 不提供啟動(dòng)事務(wù)的 API。 啟動(dòng)事務(wù)的預(yù)期方法是使用 ?set_autocommit()? 禁用自動(dòng)提交。

進(jìn)入事務(wù)后,你可以選擇在 ?commit()? 之前應(yīng)用執(zhí)行的更改,或者使用 ?rollback()? 取消它們。這些函數(shù)在 ?django.db.transaction? 中定義。

commit(using=None)

rollback(using=None)

這些函數(shù)使接受一個(gè) ?using ?參數(shù)表示所要操作的數(shù)據(jù)庫。如果未提供,則 Django 使用 "?default?" 數(shù)據(jù)庫。
當(dāng)一個(gè)原子 ?atomic()? 事務(wù)處于活動(dòng)狀態(tài)時(shí), Django 將會(huì)拒絕進(jìn)行事務(wù)提交或者事務(wù)回滾,因?yàn)檫@樣會(huì)破壞原子性。

保存點(diǎn)

保存點(diǎn)在事務(wù)中是標(biāo)記物,它可以使得回滾部分事務(wù),而不是所有事務(wù)。 SQLite, PostgreSQL, Oracle, 和 MySQL (當(dāng)使用 InnoDB 存儲(chǔ)引擎) 后端提供了保存點(diǎn)。其他后端提供了保存點(diǎn)函數(shù),但它們是空操作——它們實(shí)際上沒有做任何事情。
如果你正在使用 Django 的默認(rèn)行為——自動(dòng)提交,保存點(diǎn)并不特別有用。盡管,一旦你用 ?atomic() ?打開了一個(gè)事務(wù),那么需要構(gòu)建一系列的等待提交或回滾的數(shù)據(jù)庫操作。如果發(fā)出回滾,那么會(huì)回滾整個(gè)事務(wù)。保存點(diǎn)有能力執(zhí)行顆粒度級(jí)別的回滾,而不是由 ?transaction.rollback()? 執(zhí)行的完全回滾。
當(dāng)嵌套了 ?atomic()? 裝飾器,它會(huì)創(chuàng)建一個(gè)保存點(diǎn)來允許部分提交或回滾。強(qiáng)烈推薦只使用 ?atomic()? 而不是下面描述的函數(shù),但它們?nèi)匀皇枪?API 的一部分,而且沒計(jì)劃要棄用它們。
這里的每一個(gè)函數(shù)使用 ?using ?參數(shù),這個(gè)參數(shù)為應(yīng)用的數(shù)據(jù)庫名。如果沒有 ?using ?參數(shù),那么會(huì)使用 "?default?" 數(shù)據(jù)庫。
保存點(diǎn)由 ?django.db.transaction?中的三個(gè)函數(shù)來控制:

savepoint(using=None)

創(chuàng)建新的保存點(diǎn)。這標(biāo)志著事務(wù)中已知處于“良好”狀態(tài)的一個(gè)點(diǎn)。返回保存點(diǎn)ID (?sid?) 。

savepoint_commit(sid, using=None)

釋放保存點(diǎn) ?sid ?。自保存點(diǎn)被創(chuàng)建依賴執(zhí)行的更改成為事務(wù)的一部分。

savepoint_rollback(sid, using=None)

回滾事務(wù)來保存 ?sid ?。

如果不支持保存點(diǎn)或數(shù)據(jù)庫在自動(dòng)模式時(shí),這些函數(shù)不執(zhí)行操作。

另外,還有一個(gè)實(shí)用功能:

clean_savepoints(using=None)

重置用于生成唯一保存點(diǎn)ID的計(jì)數(shù)器。

下面的例子演示保存點(diǎn)的用法:

from django.db import transaction

# open a transaction
@transaction.atomic
def viewfunc(request):

    a.save()
    # transaction now contains a.save()

    sid = transaction.savepoint()

    b.save()
    # transaction now contains a.save() and b.save()

    if want_to_keep_b:
        transaction.savepoint_commit(sid)
        # open transaction still contains a.save() and b.save()
    else:
        transaction.savepoint_rollback(sid)
        # open transaction now contains only a.save()

保存點(diǎn)可能通過執(zhí)行部分回滾來恢復(fù)數(shù)據(jù)庫錯(cuò)誤。如果你在 ?atomic()? 塊中執(zhí)行此操作,那么整個(gè)塊將仍然被回滾,因?yàn)樗恢滥阋呀?jīng)處理了較低級(jí)別的情況。為了防止發(fā)生,你可以使用下面的函數(shù)控制回滾行為。

get_rollback(using=None)

set_rollback(rollback, using=None)

當(dāng)存在內(nèi)部原子塊時(shí),設(shè)置回滾標(biāo)記為 ?True ?將強(qiáng)制回滾。這對于觸發(fā)回滾而不引發(fā)異??赡芎苡杏?。
將它設(shè)置為 ?False ?會(huì)防止這樣的回滾。在這樣做之前,確保你已經(jīng)將事務(wù)回滾到當(dāng)前原子塊中一個(gè)正常的保存點(diǎn)。否則你會(huì)破壞原子性并且可能發(fā)生數(shù)據(jù)損壞。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)