AWS CLI での DynamoDB TransactWriteItems

トランザクション全体は 1 つの --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 個の Put / Update / Delete / ConditionCheck アクション、合計 4 MB、値は DynamoDB JSON です。アクションは同一アカウント・同一リージョン内の複数テーブルにまたがれますが、そのうち 2 つが同じアイテムを対象にすることはできません。

  • 3 つの終了コード、3 つの異なる失敗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 付きで再実行すると、構造が丸ごと届きます。アクション 1 つにつき 1 エントリ、--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"
            }
        ]
    }

    ここでは 1 つ目の更新の Awards >= 1 という条件が失敗しました。None は 2 つ目のアクションが潔白であることを示し、そのエントリには Message フィールドがそもそも無い点にも注目してください。それ以外のコードはすべて TransactionCanceledException のページで読み解いています

  • 同じアイテムを 2 回対象にするのはキャンセルではありません。何も試みられる前に検証で失敗するので、表示すべき理由も存在しません。

    aws: [ERROR]: An error occurred (ValidationException) when calling the TransactWriteItems operation: Transaction request cannot include multiple operations on one item
  • ConditionCheck — トランザクションが変更しないアイテムに対して条件を主張し、失敗すればトランザクション全体を拒否します。

  • --client-request-token — 固定のトークンは、再実行を 10 分間べき等にします。パラメータを 1 つでも変えて同じトークンを再利用すると、DynamoDB は新しいペイロードを黙って適用するのではなく IdempotentParameterMismatch を返します。

  • 配列はファイルに置きましょう--transact-items file://transaction.json はシェルのクォートを完全に回避でき、ファイルは差分も取れます。

2 倍はシェルから計測できる

同じ単一アイテムの更新を、トランザクションの中と外で 1 回ずつ、どちらも --return-consumed-capacity TOTAL 付きで実行します。DynamoDB Local は、トランザクション書き込みに 2.0 キャパシティユニット、素の書き込みに 1.0 を報告します。準備とコミットがそれぞれ課金されるのです。

これが、既定でトランザクションに手を伸ばすことへの反論のすべてです。単一アイテムのアトミック性なら、1 回しか課金されない条件付き書き込みという、より安い道具が既に手元にあります。これを何百万回も行うワークロードの値付けには、DynamoDB 料金計算ツールが 2 倍になった書き込み回数をそのまま受け取ります。シェルで DynamoDB JSON を組み立てるのをやめたいのなら、DynoTableが実テーブルに対してアイテムを編集し、生成した式を見せてくれます。

関連する例

参考資料

最終検証日 2026-07-28、上記にリンクした公式 AWS ドキュメントに照らして確認しました。

Console なしで DynamoDB を扱う

DynamoDB では実行できない本物の SQL(JOINs、GROUP BY、集計)を実行する高速な DynamoDB デスクトップクライアント。ビジュアル編集と、あなた自身の Bedrock キーで動く AI エージェントを備えています。

30日間無料トライアル、クレジットカード不要 — その後は期限のない Free プラン。