Python (boto3) での DynamoDB TransactWriteItems

transact_write_items は、最大100個の書き込みを1つのオール・オア・ナッシングの操作にまとめます。すべてのアクションがコミットされるか、まったく何も起きないかのどちらかです。boto3 の低レベルクライアントでは、PutUpdateDeleteConditionCheck のアクションを混在させた TransactItems リストを渡します。それぞれ任意の条件付きです。

Code

import boto3

client = boto3.client("dynamodb")

# Move one award between two songs — atomically. If the first song has no
# award to give, NEITHER update happens.
try:
    client.transact_write_items(
        TransactItems=[
            {
                "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"}},
                }
            },
        ]
    )
    print("Transaction committed")
except client.exceptions.TransactionCanceledException as e:
    # One reason per action, in TransactItems order. Code "None" means that
    # action was fine — some OTHER action sank the transaction.
    codes = [reason["Code"] for reason in e.response["CancellationReasons"]]
    print(f"Transaction canceled: {codes}")  # e.g. ['ConditionalCheckFailed', 'None']

Explanation

  • TransactItems — 最大100個の Put / Update / Delete / ConditionCheck アクション、集計4 MB、値は DynamoDB JSON。アクションは複数のテーブルにまたがれます(同一アカウント + リージョン)が、2つのアクションが同じアイテムを対象にすることはできません — それだけでトランザクションがキャンセルされます。
  • ConditionCheck — トランザクションが変更しないアイテムに条件をアサートし(例: 「アカウントがまだ存在する」)、失敗した場合はトランザクション全体を拒否します。
  • TransactionCanceledException — 処理すべき唯一のエラーです。e.response["CancellationReasons"] は、アクションごとに1つの {"Code", "Message"} を順に列挙します。コードには ConditionalCheckFailedTransactionConflict(別のトランザクションが処理中にアイテムに触れた — バックオフ付きでリトライしても安全)、ProvisionedThroughputExceededValidationError が含まれます。None は無実のアクションを示します。アクションに "ReturnValuesOnConditionCheckFailure": "ALL_OLD" を設定すると、その理由に負けたアイテムの属性が得られます。
  • ClientRequestToken — これを渡すと呼び出しが10分間べき等になります。ネットワークタイムアウト後の botocore リトライで、書き込みを2回適用できなくなります。
  • コスト — トランザクション書き込みはアイテムごとに2つの基礎的な書き込みを消費し(準備 + コミット)、プレーンな書き込みの約2× の WCU を課金します。単一アイテムの条件付き書き込みがすでに1アイテムのアトミック性を提供しているときは、トランザクションに手を伸ばさないでください。

Do it visually

各アクション内の条件式と更新式が厄介な部分です。DynamoDB Expression Builder がそれらを name/value マップとともに組み立て、実行可能な boto3 コードをコピーします。

アイテムを編集し、生成された式を GUI でレビューするには — DynoTable をダウンロードしてください。

References

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

Console なしで DynamoDB を扱う

DynoTable は DynamoDB 向けの高速なデスクトップクライアントです — テーブルを閲覧し、SQL スタイルのクエリを実行し、アイテムをローカルで編集できます。