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