用 AWS CLI 執行 DynamoDB TransactWriteItems

整筆交易是以一個 --transact-items JSON 陣列送進 aws dynamodb transact-write-items 的,所以有趣的部分在 CLI 的邊角:引號會在哪裡壞掉、結束碼是什麼意思,以及預設的錯誤輸出會把你除錯取消原因時最需要的那個欄位丟掉。交易替你買到了什麼在每一套 SDK 裡都是一樣的。

程式碼

aws dynamodb transact-write-items \
  --transact-items '[
    {
      "Update": {
        "TableName": "Music",
        "Key": {"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
        "UpdateExpression": "SET #upd0 = #upd0 - :one",
        "ConditionExpression": "#upd0 >= :one",
        "ExpressionAttributeNames": {"#upd0": "Awards"},
        "ExpressionAttributeValues": {":one": {"N": "1"}}
      }
    },
    {
      "Update": {
        "TableName": "Music",
        "Key": {"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "A Mis Abuelos"}},
        "UpdateExpression": "SET #upd0 = if_not_exists(#upd0, :zero) + :one",
        "ExpressionAttributeNames": {"#upd0": "Awards"},
        "ExpressionAttributeValues": {":one": {"N": "1"}, ":zero": {"N": "0"}}
      }
    }
  ]'

已提交的交易什麼都不會印,並以 0 結束。沒有回應主體可以檢查,所以在腳本裡,結束碼就是結果。

說明

  • --transact-items — 最多 100 個 PutUpdateDeleteConditionCheck 動作,總量 4 MB,值用 DynamoDB JSON。這些動作可以橫跨同一帳戶與同一區域內的多張資料表,而其中任兩個都不可以指向同一個項目。

  • 三種結束碼,三種不同的失敗0 是提交成功。252 代表 CLI 自己的參數驗證回絕了這個請求,什麼都沒送出去。254 代表 DynamoDB 回答了,而它說不行。這個區別值得拿來分支:252 是你 JSON 裡的臭蟲,254 則可能是一個你本來就預期會失敗的條件。

  • 預設的錯誤格式會把每個動作的原因丟掉。aws-cli v2 印出摘要,然後告訴你它把細節扣住了:

    aws: [ERROR]: An error occurred (TransactionCanceledException) when calling the TransactWriteItems operation: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]
    
    Additional error details:
    CancellationReasons: <complex value>
    Use "--cli-error-format json" or another error format to see the full details.

    --cli-error-format json 重跑同一條指令,結構就會完整抵達,每個動作一筆,順序與 --transact-items 相同:

    {
        "Message": "Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]",
        "Code": "TransactionCanceledException",
        "CancellationReasons": [
            {
                "Code": "ConditionalCheckFailed",
                "Message": "The conditional request failed"
            },
            {
                "Code": "None"
            }
        ]
    }

    這裡是第一個 update 的 Awards >= 1 條件失敗了;None 標示第二個動作是無辜的,而且請注意它根本沒有帶 Message 欄位。其餘每一個代碼都在 TransactionCanceledException 頁面上解碼

  • 對同一個項目下手兩次不算取消。它在任何動作被嘗試之前就沒通過驗證,這也是為什麼根本沒有原因可以印:

    aws: [ERROR]: An error occurred (ValidationException) when calling the TransactWriteItems operation: Transaction request cannot include multiple operations on one item
  • ConditionCheck — 對一個交易並不修改的項目主張某個條件,若它失敗就否決整筆交易。

  • --client-request-token — 固定的 token 會讓重跑在 10 分鐘內具備冪等性。用同一個 token 卻改了任何參數,DynamoDB 會回 IdempotentParameterMismatch,而不是默默套用新的酬載。

  • 把陣列放進檔案--transact-items file://transaction.json 完全避開 shell 引號問題,而且檔案可以 diff。

那個 2× 從 shell 就量得出來

把同一次單一項目的更新跑兩遍,一次在交易裡、一次在交易外,兩次都帶 --return-consumed-capacity TOTAL。DynamoDB Local 對交易式寫入回報 2.0 個容量單位,對普通寫入回報 1.0:準備與提交各自都要計費。

這就是「別預設就伸手去拿交易」的全部論據。要在單一項目上取得不可分割性,你手上已經有一個更便宜的工具 — 條件式寫入,它只計費一次。若要替一個會做上百萬次這種事的工作負載估價,DynamoDB 定價計算機可以直接吃下那個翻倍後的寫入次數。如果你想停手的是在 shell 裡組 DynamoDB JSON 這件事,DynoTable 能對真實資料表編輯項目,並把它產生的運算式顯示給你看。

相關範例

參考資料

最後驗證於 2026-07-28,對照上方連結的 AWS 官方文件。

不必透過主控台就能操作 DynamoDB

一款快速的 DynamoDB 桌面用戶端,可執行 DynamoDB 無法執行的真正 SQL — JOINs、GROUP BY、聚合 — 並支援視覺化編輯與使用你自己的 Bedrock 金鑰的 AI 代理。

30 天免費試用,無需信用卡 — 之後為無時間限制的免費方案。