Gravação condicional no DynamoDB em Python (boto3)

Uma gravação condicional anexa uma ConditionExpression a um put_item, update_item ou delete_item: o DynamoDB a avalia contra o item atual e aplica a gravação apenas se ela for verdadeira — atomicamente, sem race de read-modify-write. É o primitivo de optimistic locking do DynamoDB. Este exemplo protege uma atualização com uma verificação de versão.

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

Explicação

  • ConditionExpression — verificada contra o item armazenado atomicamente com a gravação. Funções disponíveis: attribute_exists, attribute_not_exists, attribute_type, contains, begins_with, size, mais comparadores (=, <>, <, >, <=, >=, BETWEEN, IN) e AND/OR/NOT.
  • Os dois idiomas de trabalho:
    • attribute_exists(#key) em uma atualização = "somente-atualizar, nunca criar". Sem ele, update_item em uma chave ausente cria o item silenciosamente (o bug de upsert acidental).
    • attribute_not_exists(#key) em um put = "somente-criar, nunca sobrescrever" — mostrado na página do PutItem.
  • Optimistic locking — leia o item (versão 7), depois grave com #version = :expectedVersion ao passar para 8. Dois gravadores concorrentes não podem ambos vencer; o perdedor recebe ConditionalCheckFailedException, relê e tenta de novo na nova versão.
  • ReturnValuesOnConditionCheckFailure="ALL_OLD" — coloca o item atual na resposta da exceção (e.response), poupando o get_item de acompanhamento após uma verificação falha. Ele consome nenhuma capacidade de leitura; uma gravação condicional falha ainda cobra sua tentativa de gravação.
  • Na API resource a mesma proteção é table.update_item(..., ConditionExpression=Attr("Version").eq(7) & Attr("Artist").exists()) com valores nativos do Python.

Faça visualmente

Condition expressions são exatamente o que o DynamoDB Expression Builder constrói — escolha a função, obtenha a expressão + mapas de nome/valor como código boto3 executável.

Para editar itens com expressões geradas e revisáveis em vez de placeholders digitados à mão — baixe o DynoTable.

Exemplos relacionados

References

Última verificação em 2026-07-13 contra a documentação oficial da AWS vinculada acima.

Trabalhe com o DynamoDB sem o Console

O DynoTable é um cliente desktop rápido para o DynamoDB — navegue pelas tabelas, execute consultas no estilo SQL e edite itens localmente.