Escritura condicional en DynamoDB con la AWS CLI
Una escritura condicional es sencilla de enviar desde la shell e incómoda de leer, porque el resultado interesante de una que falla llega como error en lugar de como salida. Las expresiones de condición de DynamoDB cubren qué puede expresar la condición; esta página trata de ejecutar una desde la CLI y sacar del error el Item que perdió la carrera.
Código
aws dynamodb update-item \
--table-name 'Music' \
--key '{"Artist":{"S":"Arturo Sandoval"},"SongTitle":{"S":"Cubano Chant"}}' \
--update-expression 'SET #upd0 = :updValue0, #version = :newVersion' \
--condition-expression 'attribute_exists(#cond0) AND #version = :expectedVersion' \
--expression-attribute-names '{"#upd0":"Genre","#version":"Version","#cond0":"Artist"}' \
--expression-attribute-values '{":updValue0":{"S":"Latin Jazz"},":expectedVersion":{"N":"7"},":newVersion":{"N":"8"}}'Si tiene éxito, el comando no imprime nada y sale con 0. Si otro escritor llegó antes, la condición falla y la CLI informa del mensaje del servicio:
An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation:
The conditional request failedExplicación
- El éxito es silencioso. Sin salida, código 0. No hay nada que parsear ni sobre lo que aseverar, así que un script de shell tiene que tratar el estado de salida como el resultado. Añade
--return-values ALL_NEWsi quieres que imprima el Item actualizado. - El fallo es el estado de salida 254, que es el código de la CLI v2 para un error del lado del cliente y lo comparte con una petición mal formada. Ramifica según el mensaje antes de reintentar, o una errata en tu expresión se convierte en un bucle de backoff infinito.
--return-values-on-condition-check-failure ALL_OLDsí funciona aquí. Los valores válidos sonALL_OLDyNONE, y no consume capacidad de lectura. Sacar el Item del error cuesta un flag más, que se explica abajo.- La condición y la actualización son flags separados con un espacio de nombres compartido.
--expression-attribute-namesy--expression-attribute-valuesse fusionan entre--update-expressiony--condition-expression, y por eso los nombres generados van#upd0,#cond0en vez de reiniciarse por cláusula. Reutiliza un marcador de posición para dos significados distintos y el segundo gana en silencio. - Una escritura fallida también se factura. La Developer Guide es explícita: una condición que se evalúa como falsa consume capacidad de escritura igualmente, dimensionada según el mayor entre el Item antiguo y el nuevo. Las condiciones no son una sonda de existencia barata.
La salida de error, y cómo sacar el Item de ella
Ejecuta el bloque una vez y tiene éxito en silencio. Ejecútalo una segunda vez, cuando Version ya no es 7, y aws-cli/2.36.9 imprime en stderr:
aws: [ERROR]: An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation: The conditional request failedAñade --return-values-on-condition-check-failure ALL_OLD y la salida por defecto te dice que hay más, sin mostrarlo:
aws: [ERROR]: An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation: The conditional request failed
Additional error details:
Item: <complex value>
Use "--cli-error-format json" or another error format to see the full details.<complex value> es el Item, retenido por el renderizador de texto por defecto. Añade --cli-error-format json y se imprime entero:
{
"Message": "The conditional request failed",
"Code": "ConditionalCheckFailedException",
"Item": {
"Artist": {"S": "Arturo Sandoval"},
"Year": {"N": "1994"},
"Version": {"N": "8"},
"SongTitle": {"S": "Cubano Chant"},
"AlbumTitle": {"S": "Danzon"},
"Genre": {"S": "Latin Jazz"}
}
}(Los mapas de atributos están plegados a una línea cada uno; todo lo demás es tal cual se imprime.) Version es 8 y Genre está puesto porque la primera ejecución tuvo éxito. Ese es el bucle de bloqueo optimista cerrado desde un script de shell: canaliza stderr por jq -r '.Item.Version.N', devuélvelo como :expectedVersion y reintenta. Sin get-item, y sin ventana entre la lectura y el reintento para que se cuele un tercer escritor.
Los reintentos no son gratis. Cada intento rechazado consume una unidad de escritura, así que una clave disputada bajo un bucle cerrado factura sin parar mientras no avanza. La calculadora de precios convierte una tasa de escritura en una cifra mensual si quieres saber cuánto cuesta de verdad una tormenta de reintentos antes de limitar los intentos.
Para ejecutar estas guardas contra tus propias tablas sin escapar los mapas de marcadores en la shell, descarga DynoTable.
Ejemplos relacionados
- Escritura condicional en DynamoDB en Node.js — el mismo bloqueo optimista con el SDK de AWS v3.
- Escritura condicional en DynamoDB en Python — el mismo bloqueo optimista con boto3.
- DynamoDB PutItem con la AWS CLI — el put de solo creación con
attribute_not_exists. - Expresiones de condición de DynamoDB — todas las funciones, con patrones.
- Entender ReturnValues — qué te da cada opción de retorno.
- DynamoDB ConditionalCheckFailedException — cuándo la comprobación fallida es esperada y cómo manejarla barato.
Referencias
- UpdateItem — Amazon DynamoDB API Reference
- update-item — AWS CLI Command Reference
- Condition expressions — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-28 contra la documentación oficial de AWS enlazada arriba.