Amazon DynamoDB Transactions:運作方式 - Amazon DynamoDB

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

Amazon DynamoDB Transactions:運作方式

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

TransactWriteItems API

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

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

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

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

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

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

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

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

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

交易完成後,在該交易中所做的變更會傳播到全域次要索引 (GSIs)、串流和備份。由於傳播不是立即或瞬時,如果資料表從備份 (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 動作歸成一組。這些動作最多可以鎖定相同 AWS 帳戶和區域中一或多個 DynamoDB 資料表中的 100 個不同項目。交易中項目的彙總大小不能超過 4 MB。

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

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

讀取的錯誤處理

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

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

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

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

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

DynamoDB 交易的隔離層級

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

SERIALIZABLE

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

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

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

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

  • TransactWriteItems 操作和 TransactGetItems 操作之間。

雖然交易操作與BatchWriteItem操作中的每個個別標準寫入之間都有可序列化的隔離,但交易與BatchWriteItem操作之間沒有可序列化的隔離。

同樣地,交易操作與 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請求的可序列化隔離層級,您應該使用 。

如果對屬於相同交易寫入請求的多個項目進行非交易讀取,則您可以讀取其他項目的新狀態和其他項目的舊狀態。只有在收到交易寫入的成功回應時,您才能讀取交易寫入請求中所有項目的新狀態。

READ-COMMITTED

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

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

操作摘要

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

作業 隔離層級

DeleteItem

可序列化

PutItem

可序列化

UpdateItem

可序列化

GetItem

可序列化

BatchGetItem

專供讀取*

BatchWriteItem

NOT 可序列化 *

Query

專供讀取

Scan

專供讀取

其他交易操作

可序列化

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

DynamoDB 中的交易衝突處理

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

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

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

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

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

  • 如果 TransactWriteItemsTransactGetItems 內的項目層級請求遭到拒絕,則請求失敗並顯示 TransactionCanceledException。如果該請求失敗, AWS SDKs請勿重試該請求。

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

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

每個失敗項目層級請求的TransactionConflict CloudWatch 指標都會遞增。

在 DynamoDB Accelerator (DAX) APIs中使用交易

TransactWriteItems DynamoDB Accelerator (DAX) 支援 TransactGetItems 和 ,其隔離層級與 DynamoDB 相同。

TransactWriteItems 透過 寫入DAX。DAX 會將TransactWriteItems呼叫傳遞給 DynamoDB 並傳回回應。若要在寫入後填入快取,TransactWriteItems請在操作TransactGetItems中每個項目的背景中DAX呼叫 ,這會消耗額外的讀取容量單位。(如需詳細資訊,請參閱 交易的容量管理。) 此功能可讓您讓應用程式邏輯保持簡單,並DAX同時用於交易操作和非交易操作操作。

TransactGetItems 呼叫會通過,DAX而不會在本機快取項目。這與 APIs中強烈一致讀取的行為相同DAX。

交易的容量管理

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

為資料表佈建容量APIs時,請規劃交易所需的其他讀取和寫入。例如,假設您的應用程式每秒執行一項交易,而每項交易會在您的資料表中寫入三個 500 位元組的項目。每個項目需要兩個寫入容量單位 (WCUs):一個用於準備交易,一個用於遞交交易。因此,您需要將六個 佈建WCUs到資料表。

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

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

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

交易的最佳實務

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

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

  • 如果您不使用 AWS 提供的 SDK,請在TransactWriteItems撥打電話時包含 ClientRequestToken 屬性,以確保請求是不具有效力的。

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

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

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

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

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

DynamoDB 交易中包含的操作僅保證在最初執行交易的區域中進行交易。當交易內套用的變更跨區域複寫至全域資料表複本時,不會保留交易性。

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

DynamoDB 交易為AWSLabs交易用戶端程式庫提供更具成本效益、強大且效能更佳的替代。建議您更新應用程式以使用原生伺服器端交易 APIs。