Amazon DynamoDB Transactions:運作方式 - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Amazon DynamoDB Transactions:運作方式

使用 Amazon DynamoDB 交易,您可以將多個動作分組在一起,然後將它們作為單一 all-or-nothing TransactWriteItemsTransactGetItems作業提交。下列各節說明 API 操作、容量管理、最佳實務,以及關於在 DynamoDB 中使用交易操作的其他詳細資訊。

TransactWriteItems API

TransactWriteItems是同步且冪等的寫入作業,可在單 all-or-nothing 一作業中將多達 100 個寫入動作分組。這些動作可以將目標鎖定為一或多個 DynamoDB 資料表 (在相同的 AWS 帳戶和區域) 中的 100 個不同項目。交易中項目的彙總大小不能超過 4 MB。這些動作的完成具有不可分割性,也就是全部成功或全部失敗。

注意
  • TransactWriteItems 操作與 BatchWriteItem 操作的不同之處,在於前者所包含的全部動作,都必須順利地完成,否則就完全不會進行變更。如果是使用 BatchWriteItem 操作,即可允許批次中只有某些動作順利完成 (其他的動作失敗)。

  • 無法使用索引執行交易。

在同一筆交易中,您無法針對同一個項目進行多項操作。例如,您不能對同一筆交易中的同一個項目既執行 ConditionCheck 又執行 Update 動作。

您可以將下列類型的動作新增到交易中:

  • Put:發起 PutItem 操作,來建立新的項目,或是用新的項目取代舊的項目 (具有條件或不指定任何條件)。

  • Update:發起 UpdateItem 操作,來編輯現有項目的屬性,或是在新項目尚未存在時,將新項目加入到資料表。利用此項動作,來新增、刪除或更新現有項目的屬性 (具有條件或無條件)。

  • Delete:發起 DeleteItem 操作,透過指定資料表中某項目的主索引鍵,來刪除該單一項目。

  • ConditionCheck:查看某項目是否存在,或是查看某項目特定屬性的條件。

交易順利完成後,該交易內完成的變更會傳播到全域次要索引 (GSI)、串流和備份。由於傳輸不是立即或即時的,所以如果資料表是從 backup (RestoreTableFromBackup) 還原或匯出到時間點 (ExportTableToPointInTime) 中間傳輸,它可能會包含最近交易期間所做的一些變更,但不是所有變更。

冪等性

在進行 TransactWriteItems 呼叫時,您可以選擇性地加入用戶端符記,以確保請求具有冪等性。如果讓交易具有冪等性,則在因為連線逾時或其他連線問題,而多次提交同一項操作時,有助於防止應用程式發生錯誤。

如果原始的 TransactWriteItems 呼叫順利完成,便會成功傳回後續具有相同用戶端字符的 TransactWriteItems 呼叫,不建立任何變更。如果設定了 ReturnConsumedCapacity 參數,則初始的 TransactWriteItems 呼叫會傳回在建立變更時所使用的寫入容量單位數量。後續具有相同用戶端符記的 TransactWriteItems 呼叫,會傳回在讀取項目時所用掉的讀取容量單位數量。

關於等冪性的重點
  • 用戶端符記在使用該符記的請求完成後 10 分鐘內為有效。10 分鐘過後,使用同一個用戶端符記的任何請求,會被視為新的請求。在經過 10 分鐘之後,您就不應該針對相同的請求,重複使用同一個用戶端符記。

  • 如果您在 10 分鐘的冪等性有效期間內,使用相同的用戶端符記來重複請求,但變更了其他的某些請求參數,則 DynamoDB 會傳回 IdempotentParameterMismatch 例外。

寫入的錯誤處理

在下列的情況中,寫入交易不會成功:

  • 當其中一個條件表達式中的條件不符時。

  • 因為在同一個 TransactWriteItems 操作中,有超過一個以上的動作鎖定相同的項目,而造成交易驗證錯誤時。

  • 如果 TransactWriteItems 請求與 TransactWriteItems 請求中一或多個項目持續執行的 TransactWriteItems 操作相互衝突時。在這種情況中,請求會失敗,並且丟出 TransactionCanceledException 例外。

  • 佈建的容量不足,而使交易無法完成時。

  • 當項目的大小過大 (超過 400 KB)、本機次要索引 (LSI) 變得過大,或是因為交易所進行的變更造成類似的驗證錯誤時。

  • 發生使用者錯誤時,例如無效的資料格式。

如需如何處理 TransactWriteItems 操作衝突的詳細資訊,請參閱 DynamoDB 中的交易衝突處理

TransactGetItems API

TransactGetItems 是一項同步讀取操作,可將最多 100 個 Get 動作歸成一組。這些動作可以將目標鎖定為一或多個 DynamoDB 資料表 (在相同的 AWS 帳戶和區域) 中的 100 個不同項目。交易中項目的彙總大小不能超過 4 MB。

Get 動作的執行具有不可分割性,也就是全部成功或全部失敗:

  • Get:發起 GetItem 操作,針對具有指定主索引鍵的項目,擷取該項目的一組屬性。如果找不到符合的項目,則 Get 不會傳回任何資料。

讀取的錯誤處理

在下列的情況中,讀取交易不會成功:

  • 如果 TransactGetItems 請求與 TransactGetItems 請求中一或多個項目持續執行的 TransactWriteItems 操作相互衝突時。在這種情況中,請求會失敗,並且丟出 TransactionCanceledException 例外。

  • 佈建的容量不足,而使交易無法完成時。

  • 發生使用者錯誤時,例如無效的資料格式。

如需如何處理 TransactGetItems 操作衝突的詳細資訊,請參閱 DynamoDB 中的交易衝突處理

DynamoDB 交易的隔離層級

交易操作 (TransactWriteItemsTransactGetItems) 和其他操作的隔離層級如下。

可序列化

如果在前一項操作完成之前,沒有任何操作開始執行,則可序列化隔離可確保多個同時並行操作的結果會相同。

在下列的操作類型之間,具有可序列化的隔離層級:

  • 在任何交易操作和任何標準寫入操作 (PutItemUpdateItemDeleteItem) 之間。

  • 在任何交易操作和任何標準讀取操作 (GetItem) 之間。

  • TransactWriteItems 操作和 TransactGetItems 操作之間。

雖然事務性操作之間存在可序列化隔離,以及操作中的每個單獨的標準寫入,但是事務與作為一個單元的BatchWriteItemBatchWriteItem作之間沒有可序列化的隔離。

同樣地,交易操作與 BatchGetItem 操作中個別 GetItems 之間的隔離層是可以序列化。但是交易與當作一個單位的 BatchGetItem 操作之間的隔離層是專供讀取

單一 GetItem 請求是兩種可序列化的 TransactWriteItems 請求方式之一,可以發生在 TransactWriteItems 請求之前或之後。與 TransactWriteItems 請求同時發出的多個 GetItem 請求,能夠以任何順序執行,因此結果會是專供讀取

例如,如果項目 A 和項目 B 的 GetItem 請求與修改項目 A 和項目 B 的 TransactWriteItems 請求同時執行,則會有四種可能性:

  • 兩個 GetItem 請求皆會在 TransactWriteItems 請求之前執行。

  • 兩個 GetItem 請求皆會在 TransactWriteItems 請求之後執行。

  • 項目 A 的 GetItem 請求會在 TransactWriteItems 請求之前執行。針對項目 B,GetItem 會在 TransactWriteItems 之後執行。

  • 項目 B 的 GetItem 請求會在 TransactWriteItems 請求之前執行。針對項目 A,GetItem 會在 TransactWriteItems 之後執行。

TransactGetItems如果您更喜歡多GetItem個請求的可序列化隔離級別,則應該使用。

如果在執行中屬於相同交易寫入要求的多個項目上進行非交易讀取,您可能能夠讀取某些項目的新狀態和其他項目的舊狀態。只有在收到交易寫入的成功回應時,您才能讀取屬於交易寫入要求一部分的所有項目的新狀態。

專供讀取

專供讀取隔離可確保讀取操作對特定項目一律傳回已確認的值 - 如果交易寫入最終未成功,則讀取操作一律不向該項目呈現此寫入狀態的檢視。專供讀取隔離不會防止在讀取操作後立即修改項目。

在任何交易操作和牽涉到多次標準讀取 (BatchGetItemQueryScan) 的任何讀取操作之間,其隔離層級為專供讀取。如果交易寫入在 BatchGetItemQueryScan 操作期間更新項目,則讀取操作的後續部分會傳回新確認的值 (含有 ConsistentRead) 或可能是先前已確認的值(最終一致讀取)。

操作摘要

做為總結,下表顯示了交易操作 (TransactWriteItemsTransactGetItems) 和其他操作之間的隔離層級。

操作 隔離層級

DeleteItem

可序列化

PutItem

可序列化

UpdateItem

可序列化

GetItem

可序列化

BatchGetItem

專供讀取*

BatchWriteItem

不可序列化*

Query

專供讀取

Scan

專供讀取

其他交易操作

可序列化

標有星號的層級 (*) 適用於單位式操作。不過,這些操作內的個別動作具有可序列化的隔離層級。

DynamoDB 中的交易衝突處理

在交易內的項目上進行並行項目層級請求期間,可能會發生交易衝突。下列情境可能發生交易衝突:

  • 項目的 PutItemUpdateItemDeleteItem 請求與包括相同項目的持續 TransactWriteItems 請求發生衝突。

  • TransactWriteItems 請求內的項目是另一個持續 TransactWriteItems 請求的一部分。

  • TransactGetItems 請求的項目是持續 TransactWriteItemsBatchWriteItemPutItemUpdateItemDeleteItem 請求的一部分。

注意
  • PutItemUpdateItemDeleteItem 請求遭到拒絕時,請求失敗並顯示 TransactionConflictException

  • 如果 TransactWriteItemsTransactGetItems 內的項目層級請求遭到拒絕,則請求失敗並顯示 TransactionCanceledException。如果該請求失敗,AWS 開發套件不會重試請求。

    如果您使用的是AWS SDK for Java,例外狀況會包含的清單 CancellationReasons,根據 TransactItems request 參數中的項目清單進行排序。對於其他語言,清單的字串表示法會併入異常的錯誤訊息中。

  • 不過,如果有持續執行的 TransactWriteItemsTransactGetItems 操作,與同時並行的 GetItem 請求相互衝突時,這兩項操作都可以順利完成。

每個失敗的項目層級要求都會增加TransactionConflict CloudWatch 量度量

使用 DynamoDB Accelerator (DAX) 中的交易 API

DynamoDB Accelerator (DAX) 中支援 TransactWriteItemsTransactGetItems,且隔離層級與在 DynamoDB 中相同。

TransactWriteItems 會透過 DAX 寫入。DAX 會將 TransactWriteItems 呼叫傳送給 DynamoDB,然後傳回回應。為在寫入後填入快取,對於 TransactWriteItems 操作中的每個項目,DAX 會在背景呼叫 TransactGetItems,並耗用更多讀取容量單位。(如需詳細資訊,請參閱 交易的容量管理。) 此功能可讓您保持簡單的應用程式邏輯,並使用 DAX 執行交易及非交易操作。

TransactGetItems 呼叫透過 DAX 傳遞,項目不在本機進行快取。這個行為與 DAX 中的強烈一致讀取 API 相同。

交易的容量管理

在您的 DynamoDB 資料表中啟用交易功能,不需額外付費。您只需針對交易中所進行的讀取和寫入付費即可。DynamoDB 會對交易中的每個項目進行兩項基本的讀取和寫入動作:一項是用來準備交易,一項是用來遞交交易。您的 Amazon CloudWatch 指標中會顯示兩個基礎讀取/寫入操作。

在為資料表佈建容量時,請規劃交易 API 所需的額外讀取與寫入容量。例如,假設您的應用程式每秒執行一項交易,而每項交易會在您的資料表中寫入三個 500 位元組的項目。每個項目需要兩個寫入容量單位 (WCU):一個單位用來準備交易,另一個單位用來遞交交易。因此,您會需要佈建六個 WCU 給該資料表。

如果您在前一個範例中使用 DynamoDB Accelerator (DAX),則也會針對 TransactWriteItems 呼叫中的每個項目使用兩個讀取容量單位 (RCU)。因此,您會需要佈建六個額外 RCU 給資料表。

同樣地,如果您的應用程式每秒執行一次讀取交易,而每項交易會在您的資料表中讀取三個 500 位元組的項目,則您會需要佈建六個讀取容量單位 (RCU) 給該資料表。讀取每個項目需要兩個 RCU:一個用來準備交易,另一個用來遞交交易。

此外,在出現 TransactionInProgressException 例外時,預設的 SDK 動作是重試交易。請規劃這些重試動作會使用的額外讀取容量單位 (RCU)。如果用您自己的程式碼,使用 ClientRequestToken 來重試交易時,也請進行同樣的規劃。

交易的最佳實務

在使用 DynamoDB 交易時,請考慮採用下列建議的做法。

  • 啟用資料表的自動調整規模功能,或是確定您已佈建足夠的輸送容量,來針對您交易中的每個項目,進行兩項讀取或寫入操作。

  • 如果您未使用 AWS 所提供的開發套件,請在發出 TransactWriteItems 呼叫時加入 ClientRequestToken 屬性,以確保請求具有冪等性。

  • 如非必要,請勿在交易中將操作歸為一組。例如,如果包含 10 項操作的單一交易,可以分成多項交易執行,而不會影響到應用程式的正確度,則我們建議拆分該項交易。簡化的交易可提升輸送量,而且成功的機率更高。

  • 更新同一個項目的多項交易如果同時執行,可能會造成衝突而導致交易取消。我們建議採用下列的 DynamoDB 資料建模最佳實務,來將此等衝突減到最少。

  • 如果在單一交易中,經常更新跨多個項目的一組屬性,請考慮將這些屬性分組成為單一項目,來縮小交易的範圍。

  • 避免使用大量擷取資料的交易。如果是大量寫入作業,較理想的做法是使用 BatchWriteItem

將交易 API 與全域資料表搭配使用

DynamoDB 交易中包含的作業只能在最初執行交易的區域中保證交易。當在交易中套用的變更跨區域複製到全域表格複本時,不會保留交易性。

交易與交易用戶端程式 AWSLabs 庫

DynamoDB 交易可為交易用戶端程式庫提供更符合成本效益、穩健且高效能的AWSLabs替代品。我們建議您更新應用程式,以使用原生的伺服器端交易 API。