NDB 交易

交易是指一項或一組不可分割的作業,這代表交易絕不會只有部分執行;交易中的所有作業不是全部執行,就是全部不執行。交易的最長持續時間為 60 秒,而在 30 秒後則有 10 秒的閒置到期時間。

應用程式可透過 NDB 非同步 API 同時管理多個獨立交易。同步 API 提供使用 @ndb.transactional() 裝飾器的簡易 API。裝飾函式是在交易內容中執行。

@ndb.transactional
def insert_if_absent(note_key, note):
    fetch = note_key.get()
    if fetch is None:
        note.put()
        return True
    return False
note_key = ndb.Key(Note, note_title, parent=parent)
note = Note(key=note_key, content=note_text)
inserted = insert_if_absent(note_key, note)

如果這個交易與其他交易「衝突」,則交易會失敗;NDB 會針對這類失敗交易自動重試幾次。在重試交易時,可能會多次呼叫此函式。嘗試的重試次數設有限制 (預設為 3 次)。如果交易仍未成功,NDB 會傳回 TransactionFailedError。如要變更重試次數,您可以將 retries=N 傳送至 transactional() 裝飾器。重試次數為 0 代表會嘗試交易一次,失敗就不會重試;重試次數為「N」代表總共會嘗試交易「N+1」次。範例:

@ndb.transactional(retries=1)
def insert_if_absent_2_retries(note_key, note):
    # do insert

交易中僅允許祖系查詢。根據預設,交易僅適用於相同實體群組的實體 (具有相同「祖系」的金鑰)。

您可以傳送 xg=True 來指定跨群組 (「XG」) 交易 (最多可允許二十五個實體群組):

@ndb.transactional(xg=True)
def insert_if_absent_xg(note_key, note):
    # do insert

跨群組交易會跨越多個實體群組運作,其行為類似於單一群組交易,但如果程式碼嘗試從一個以上的實體群組更新實體,則不會失敗。

如果函式引發例外狀況,則交易會立即取消且 NDB 會重新引發例外狀況,讓呼叫程式碼看到。您可以引發 ndb.Rollback 例外狀況 (在這個情況下,函式呼叫會傳回 None),藉此強制交易失敗而不顯示任何訊息。目前沒有任何機制可以強制重試。

您可能會有不想在交易中執行的函式。這時,請將這類函式當做回呼函式傳送至 ndb.transaction(),而不要使用 @ndb.transactional 來裝飾

def insert_if_absent_sometimes(note_key, note):
    # do insert
inserted = ndb.transaction(lambda:
                           insert_if_absent_sometimes(note_key, note))

如要測試特定程式碼是否在交易中執行,請使用 in_transaction() 函式。

您可以指定「交易」函式在受到交易中已存在程式碼叫用時的行為。@ndb.non_transactional 裝飾器會指定不得在交易中執行函式;如果在交易中呼叫函式,則會在交易外執行。@ndb.transactional 裝飾器和 ndb.transaction 函式需要使用 propagation 關鍵字引數。舉例來說,如果函式應啟動新的獨立交易,請依此裝飾函式:

@ndb.transactional(propagation=ndb.TransactionOptions.INDEPENDENT)
def insert_if_absent_indep(note_key, note):
    # do insert

傳播類型會跟其他內容選項和交易選項一併列出

如果您沒有明確掌握目前的狀況,交易行為以及 NDB 的快取行為可能會讓您感到混淆。如果您修改了交易內的實體,但尚未修訂交易,則 NDB 的內容快取會有修改過的值,但基礎資料儲存庫仍是尚未修改的值。

交易工作排入佇列

您可以將工作排入佇列做為資料儲存庫交易的一部分,以便只在成功修訂交易時才將工作排入佇列。如未修訂交易,則工作不會排入佇列。如已確實修訂交易,工作就會排入佇列。排入佇列後,工作不會立即執行,因此工作與交易並非不可分割。不過,將工作排入佇列後,該工作將不斷重試直到成功為止。這適用於裝飾函式期間排入佇列的任何工作。

您可以透過交易工作,將非資料儲存庫的動作結合至依賴交易成功的交易 (例如傳送電子郵件以確認購買),因此非常實用。您也可以將資料儲存庫動作與交易綁定,例如,只有在交易成功時,才會修訂對於交易之外的實體群組所做的變更。

在單一交易期間,應用程式最多只能將五項交易工作插入工作佇列。交易工作不能有使用者指定的名稱。

from google.appengine.api import taskqueue
from google.appengine.ext import ndb
@ndb.transactional
def insert_if_absent_taskq(note_key, note):
    taskqueue.add(url=flask.url_for('taskq_worker'), transactional=True)
    # do insert
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Python 2 適用的 App Engine 標準環境