TransactionInProgressException
TL;DR — 一個 TransactWriteItems 重試攜帶了與一個_仍在執行_的嘗試相同的 ClientRequestToken。這通常是你的用戶端逾時快於交易完成,因此 SDK 的重試與進行中的原始請求碰撞。以退避繼續重試 — 原始請求完成後的稍後重試會回傳冪等成功 — 並調校逾時,讓至少一個重試在約 5 秒後落地。
這是什麼意思
TransactionInProgressException: The transaction with the given request token
is already in progress.ClientRequestToken 使 TransactWriteItems 具冪等性:10 分鐘視窗內的相同呼叫計為一個交易。當第一次嘗試仍在處理中時,帶相同 token 的第二個呼叫尚無法被回答 — 它既不是已完成交易的重複,也不是新的 — 因此 DynamoDB 以此例外拒絕它。它是一個時機訊號,而非資料錯誤。
為什麼會發生
- 用戶端逾時短於交易延遲 — 請求逾時觸發、SDK 重試,而重試在原始交易仍在提交時抵達。
- 積極的重試政策 — 非常短的退避意味著數個重試可能堆到一個需要幾秒的交易上。
- 兩個呼叫者共用一個 token — 獨立的行程故意(或意外)並行發出相同的
ClientRequestToken。
如何修正
讓重試以指數退避繼續 — 一旦進行中的交易完成,帶相同 token 的重試會回傳成功,而不會將寫入套用兩次。將這個例外視為可重試。
依記載的指引調校逾時,讓重試能在交易穩定後落地:
- 允許至少一個重試在自第一次嘗試起經過 5 秒後被處理;
- 將每個請求的逾時設為約 1 秒或更高;
- 讓 socket 逾時略低於請求逾時;
- 在嘗試之間使用指數退避。
不要在重試時輪替 token — 每次嘗試產生新的
ClientRequestToken會默默地將重試轉為_新交易_(將寫入套用兩次)。相同意圖、相同 token,最多 10 分鐘:const token = randomUUID(); // one token per logical transaction await client.send(new TransactWriteItemsCommand({TransactItems, ClientRequestToken: token}));序列化故意的並行呼叫者 — 若兩個 worker 能提交相同的邏輯交易,讓其中一個成為擁有者或將兩者透過佇列路由。
若交易執行夠久到觸發逾時,檢查它們在爭用什麼 — DynoTable 桌面應用程式讓你檢視涉及的項目,而 DynamoDB 定價計算器顯示交易寫入的加倍寫入容量的成本。
相關錯誤
- IdempotentParameterMismatchException — 相同 token、_不同_負載。
- TransactionCanceledException — 交易本身失敗。
- TransactionConflictException — 與另一個交易的項目層級衝突。
- 程式碼範例:TransactWriteItems in Node.js — 展示 ClientRequestToken 的用法。
- 學習:DynamoDB transactions
References
- TransactWriteItems — Amazon DynamoDB API Reference
- Amazon DynamoDB Transactions: How it works — Amazon DynamoDB Developer Guide
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
最後驗證於 2026-07-13,對照上方連結的 AWS 官方文件。