Python(boto3)에서의 DynamoDB TransactWriteItems

transact_write_items는 최대 100개 쓰기를 하나의 전부 아니면 전무 연산으로 묶습니다 — 모든 액션이 커밋되거나, 하나도 커밋되지 않습니다. boto3 저수준 클라이언트에서는 Put, Update, Delete, ConditionCheck 액션을 섞은 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입니다. 액션은 여러 테이블에 걸칠 수 있지만(동일 계정 + 리전), 두 액션이 동일한 항목을 대상으로 할 수 없습니다 — 그것만으로도 트랜잭션이 취소됩니다.
  • ConditionCheck — 트랜잭션이 수정하지 않는 항목에 조건을 단언하고(예: "계정이 아직 존재함"), 실패하면 트랜잭션 전체를 거부합니다.
  • TransactionCanceledException — 처리해야 할 유일한 오류입니다. e.response["CancellationReasons"]는 순서대로 액션당 하나의 {"Code", "Message"}를 나열합니다 — 코드에는 ConditionalCheckFailed, TransactionConflict(다른 트랜잭션이 진행 중에 항목을 건드림 — 백오프와 함께 재시도해도 안전), ProvisionedThroughputExceeded, ValidationError가 포함되며, None은 무고한 액션을 표시합니다. 액션에 "ReturnValuesOnConditionCheckFailure": "ALL_OLD"를 설정하면 그 사유에 진 항목의 속성을 얻습니다.
  • ClientRequestToken — 호출을 10분 동안 멱등적으로 만들려면 하나 전달하세요. 네트워크 타임아웃 후의 botocore 재시도가 쓰기를 두 번 적용할 수 없게 됩니다.
  • 비용 — 트랜잭션 쓰기는 항목당 두 번의 기본 쓰기(준비 + 커밋)를 소비하므로, 일반 쓰기의 약 2배 WCU를 청구합니다. 단일 항목 조건부 쓰기가 이미 한 항목에 대한 원자성을 제공할 때는 트랜잭션에 손대지 마세요.

Do it visually

각 액션 안의 조건 및 업데이트 표현식이 까다로운 부분입니다 — DynamoDB Expression Builder가 이름/값 맵과 함께 이를 조립하고 실행 가능한 boto3 코드를 복사해 줍니다.

GUI에서 항목을 편집하고 생성된 표현식을 검토하려면 — DynoTable을 다운로드하세요.

References

Last verified 2026-07-13 against the official AWS documentation linked above.

Console 없이 DynamoDB 작업하기

DynoTable은 DynamoDB를 위한 빠른 데스크톱 클라이언트입니다 — 테이블을 탐색하고, SQL 스타일 쿼리를 실행하고, 항목을 로컬에서 편집하세요.