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 itemConditionCheck— トランザクションが変更しないアイテムに対して条件を主張し、失敗すればトランザクション全体を拒否します。--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が実テーブルに対してアイテムを編集し、生成した式を見せてくれます。
関連する例
- Node.js での DynamoDB TransactWriteItems — AWS SDK v3 による同じトランザクション。
- Python での DynamoDB TransactWriteItems — boto3 による同じトランザクション。
- AWS CLI での DynamoDB BatchWriteItem — アトミック性が不要なときの一括書き込み。
- DynamoDB のトランザクション — 分離性、べき等性、そしてトランザクションが割に合う場面。
- DynamoDB TransactionCanceledException — すべてのキャンセル理由コードを読み解きます。
- "Too many actions in a TransactWriteItems call" — 100 アクションと 4 MB のトランザクション上限。
- "Transaction request cannot include multiple operations on one item" — 1 トランザクションにつき、1 アイテムに 1 アクション。
参考資料
- TransactWriteItems — Amazon DynamoDB API Reference
- transact-write-items — AWS CLI Command Reference
- Amazon DynamoDB transactions: how it works — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
最終検証日 2026-07-28、上記にリンクした公式 AWS ドキュメントに照らして確認しました。