Escritura condicional en DynamoDB en Python (boto3)

Una escritura condicional adjunta una ConditionExpression a un put_item, update_item o delete_item: DynamoDB la evalúa contra el item actual y aplica la escritura solo si se cumple — atómicamente, sin una carrera de lectura-modificación-escritura. Es la primitiva de bloqueo optimista de DynamoDB. Este ejemplo protege una actualización con una comprobación de versión.

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"))

Explicación

  • ConditionExpression — comprobada contra el item almacenado atómicamente con la escritura. Funciones disponibles: attribute_exists, attribute_not_exists, attribute_type, contains, begins_with, size, más comparadores (=, <>, <, >, <=, >=, BETWEEN, IN) y AND/OR/NOT.
  • Los dos idiomas de caballo de batalla:
    • attribute_exists(#key) en una actualización = "solo actualizar, nunca crear". Sin ella, update_item sobre una clave inexistente crea silenciosamente el item (el bug del upsert accidental).
    • attribute_not_exists(#key) en una inserción = "solo crear, nunca sobrescribir" — mostrado en la página de PutItem.
  • Bloqueo optimista — lee el item (versión 7), luego escribe con #version = :expectedVersion mientras lo subes a 8. Dos escritores concurrentes no pueden ganar ambos; el perdedor recibe ConditionalCheckFailedException, vuelve a leer y reintenta sobre la nueva versión.
  • ReturnValuesOnConditionCheckFailure="ALL_OLD" — pone el item actual en la respuesta de la excepción (e.response), ahorrando el get_item posterior tras una comprobación fallida. No consume capacidad de lectura; una escritura condicional fallida sigue facturando su intento de escritura.
  • En la API de recurso, la misma protección es table.update_item(..., ConditionExpression=Attr("Version").eq(7) & Attr("Artist").exists()) con valores nativos de Python.

Hazlo visualmente

Las expresiones de condición son exactamente lo que construye el DynamoDB Expression Builder — elige la función, obtén la expresión + los mapas de nombre/valor como código boto3 ejecutable.

Para editar items con expresiones generadas y revisables en lugar de marcadores de posición escritos a mano — descarga DynoTable.

Ejemplos relacionados

References

Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.