本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
Amazon DynamoDB Transactions:運作方式
使用 Amazon DynamoDB 交易,您可以將多個動作分組在一起,並將其作為單一 all-or-nothing動作TransactWriteItems
或TransactGetItems
操作提交。下列各節說明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 交易的隔離層級
交易操作 (TransactWriteItems
或 TransactGetItems
) 和其他操作的隔離層級如下。
SERIALIZABLE
如果在前一項操作完成之前,沒有任何操作開始執行,則可序列化隔離可確保多個同時並行操作的結果會相同。
在下列的操作類型之間,具有可序列化的隔離層級:
-
在任何交易操作和任何標準寫入操作 (
PutItem
、UpdateItem
或DeleteItem
) 之間。 -
在任何交易操作和任何標準讀取操作 (
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
專供讀取隔離可確保讀取操作對特定項目一律傳回已確認的值 - 如果交易寫入最終未成功,則讀取操作一律不向該項目呈現此寫入狀態的檢視。專供讀取隔離不會防止在讀取操作後立即修改項目。
在任何交易操作和牽涉到多次標準讀取 (BatchGetItem
、Query
或 Scan
) 的任何讀取操作之間,其隔離層級為專供讀取。如果交易寫入在 BatchGetItem
、Query
或 Scan
操作期間更新項目,則讀取操作的後續部分會傳回新確認的值 (含有 ConsistentRead)
或可能是先前已確認的值(最終一致讀取)。
操作摘要
做為總結,下表顯示了交易操作 (TransactWriteItems
或 TransactGetItems
) 和其他操作之間的隔離層級。
作業 | 隔離層級 |
---|---|
|
可序列化 |
|
可序列化 |
|
可序列化 |
|
可序列化 |
|
專供讀取* |
|
NOT 可序列化 * |
|
專供讀取 |
|
專供讀取 |
其他交易操作 |
可序列化 |
標有星號的層級 (*) 適用於單位式操作。不過,這些操作內的個別動作具有可序列化的隔離層級。
DynamoDB 中的交易衝突處理
在交易內的項目上進行並行項目層級請求期間,可能會發生交易衝突。下列情境可能發生交易衝突:
-
項目的
PutItem
、UpdateItem
或DeleteItem
請求與包括相同項目的持續TransactWriteItems
請求發生衝突。 -
TransactWriteItems
請求內的項目是另一個持續TransactWriteItems
請求的一部分。 -
TransactGetItems
請求的項目是持續TransactWriteItems
、BatchWriteItem
、PutItem
、UpdateItem
或DeleteItem
請求的一部分。
注意
-
當
PutItem
、UpdateItem
或DeleteItem
請求遭到拒絕時,請求失敗並顯示TransactionConflictException
。 -
如果
TransactWriteItems
或TransactGetItems
內的項目層級請求遭到拒絕,則請求失敗並顯示TransactionCanceledException
。如果該請求失敗, AWS SDKs請勿重試該請求。如果您使用的是 AWS SDK for Java,例外狀況會包含 清單CancellationReasons,並根據
TransactItems
請求參數中的項目清單排序。對於其他語言,清單的字串表示法會併入異常的錯誤訊息中。 -
不過,如果有持續執行的
TransactWriteItems
和TransactGetItems
操作,與同時並行的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