DynamoDB Conditional Write in Python (boto3)

Ein bedingter Schreibvorgang hängt eine ConditionExpression an ein put_item, update_item oder delete_item: DynamoDB wertet sie gegen das aktuelle Item aus und wendet den Schreibvorgang nur an, wenn sie zutrifft — atomar, ohne Read-Modify-Write-Race. Es ist DynamoDBs Primitive für optimistisches Locking. Dieses Beispiel sichert ein Update mit einer Versionsprüfung ab.

Code

import boto3

client = boto3.client("dynamodb")

# Update the item only if nobody changed it since we read version 7.
try:
    client.update_item(
        TableName="Music",
        Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
        UpdateExpression="SET #upd0 = :updValue0, #version = :newVersion",
        ConditionExpression="attribute_exists(#cond0) AND #version = :expectedVersion",
        ExpressionAttributeNames={"#upd0": "Genre", "#version": "Version", "#cond0": "Artist"},
        ExpressionAttributeValues={
            ":updValue0": {"S": "Latin Jazz"},
            ":expectedVersion": {"N": "7"},
            ":newVersion": {"N": "8"},
        },
        ReturnValuesOnConditionCheckFailure="ALL_OLD",
    )
    print("Updated to version 8")
except client.exceptions.ConditionalCheckFailedException as e:
    # With ReturnValuesOnConditionCheckFailure="ALL_OLD", the current item
    # rides back on the exception — no extra read to see what beat you.
    print("Lost the race — item is now:", e.response.get("Item"))

Erklärung

  • ConditionExpressionatomar mit dem Schreibvorgang gegen das gespeicherte Item geprüft. Verfügbare Funktionen: attribute_exists, attribute_not_exists, attribute_type, contains, begins_with, size, plus Vergleichsoperatoren (=, <>, <, >, <=, >=, BETWEEN, IN) und AND/OR/NOT.
  • Die zwei Standard-Idiome:
    • attribute_exists(#key) bei einem Update = "nur aktualisieren, nie anlegen". Ohne es legt update_item auf einen fehlenden Schlüssel stillschweigend das Item an (der versehentliche Upsert-Bug).
    • attribute_not_exists(#key) bei einem Put = "nur anlegen, nie überschreiben" — gezeigt auf der PutItem-Seite.
  • Optimistisches Locking — lies das Item (Version 7), dann schreibe mit #version = :expectedVersion und erhöhe auf 8. Zwei gleichzeitige Writer können nicht beide gewinnen; der Verlierer bekommt ConditionalCheckFailedException, liest neu und wiederholt auf der neuen Version.
  • ReturnValuesOnConditionCheckFailure="ALL_OLD" — legt das aktuelle Item an die Exception-Antwort (e.response) und spart das anschließende get_item nach einer gescheiterten Prüfung. Es verbraucht keine Lesekapazität; ein gescheiterter bedingter Schreibvorgang berechnet trotzdem seinen Schreibversuch.
  • Auf der Resource-API lautet derselbe Guard table.update_item(..., ConditionExpression=Attr("Version").eq(7) & Attr("Artist").exists()) mit nativen Python-Werten.

Visuell erledigen

Bedingungsausdrücke sind genau das, was der DynamoDB Expression Builder baut — wähle die Funktion, erhalte den Ausdruck + Name-/Wert-Zuordnungen als lauffähigen boto3-Code.

Um Items mit generierten, überprüfbaren Ausdrücken zu bearbeiten statt mit handgetippten Platzhaltern — lade DynoTable herunter.

Verwandte Beispiele

References

Zuletzt verifiziert am 2026-07-13 gegen die oben verlinkte offizielle AWS-Dokumentation.

Mit DynamoDB ohne die Console arbeiten

DynoTable ist ein schneller Desktop-Client für DynamoDB — durchsuche Tabellen, führe SQL-artige Queries aus und bearbeite Items lokal.