DynamoDB Conditional Write mit der AWS CLI
Ein Conditional Write ist aus der Shell leicht abzuschicken und unangenehm zu lesen, weil das interessante Ergebnis eines fehlgeschlagenen Writes als Fehler statt als Ausgabe ankommt. DynamoDB Condition Expressions behandelt, was die Expression ausdrücken kann; auf dieser Seite geht es darum, eine aus der CLI auszuführen und das unterlegene Item aus dem Fehler herauszuholen.
Code
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"}}'Bei Erfolg gibt der Befehl nichts aus und beendet sich mit 0. War ein anderer Writer zuerst da, schlägt die Bedingung fehl und die CLI meldet die Service-Nachricht:
An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation:
The conditional request failedErklärung
- Erfolg ist still. Keine Ausgabe, Exit 0. Es gibt nichts zu parsen und nichts zu prüfen, ein Shell-Skript muss den Exit-Status also als Ergebnis behandeln. Ergänze
--return-values ALL_NEW, wenn du das aktualisierte Item ausgegeben haben willst. - Ein Fehlschlag ist Exit-Status 254, der CLI-v2-Code für einen clientseitigen Fehler, den er sich mit einem fehlerhaft aufgebauten Request teilt. Verzweige anhand der Nachricht, bevor du wiederholst — sonst wird ein Tippfehler in deiner Expression zu einer endlosen Backoff-Schleife.
--return-values-on-condition-check-failure ALL_OLDfunktioniert hier sehr wohl. Gültige Werte sindALL_OLDundNONE, und es verbraucht keine Read-Kapazität. Das Item aus dem Fehler herauszubekommen kostet ein weiteres Flag, siehe unten.- Bedingung und Update sind getrennte Flags mit gemeinsamem Namensraum.
--expression-attribute-namesund--expression-attribute-valueswerden über--update-expressionund--condition-expressionhinweg zusammengeführt — deshalb laufen die generierten Namen#upd0,#cond0durch, statt pro Klausel neu zu beginnen. Nutzt du einen Platzhalter für zwei verschiedene Bedeutungen, gewinnt stillschweigend der zweite. - Ein fehlgeschlagener Write wird trotzdem abgerechnet. Der Developer Guide ist eindeutig: Eine Bedingung, die zu false auswertet, verbraucht dennoch Write-Kapazität, bemessen am größeren von altem und neuem Item. Bedingungen sind keine günstige Existenzprüfung.
Die Fehlerausgabe — und wie du das Item daraus bekommst
Führe den Block einmal aus und er gelingt still. Führe ihn ein zweites Mal aus, wenn Version nicht mehr 7 ist, und aws-cli/2.36.9 gibt auf stderr aus:
aws: [ERROR]: An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation: The conditional request failedErgänze --return-values-on-condition-check-failure ALL_OLD und die Standardausgabe sagt dir, dass es mehr gibt, ohne es zu zeigen:
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> ist das Item, vom Standard-Text-Renderer zurückgehalten. Ergänze --cli-error-format json und das Ganze wird ausgegeben:
{
"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"}
}
}(Attribut-Maps jeweils auf eine Zeile gefaltet; alles Übrige ist so, wie es ausgegeben wurde.) Version ist 8 und Genre ist gesetzt, weil der erste Lauf erfolgreich war. Das ist die Optimistic-Locking-Schleife, aus einem Shell-Skript geschlossen: leite stderr durch jq -r '.Item.Version.N', gib das als :expectedVersion zurück, wiederhole. Kein get-item und kein Fenster zwischen Lesen und Wiederholung, in das ein dritter Writer schlüpfen könnte.
Die Wiederholungen sind nicht kostenlos. Jeder abgelehnte Versuch verbraucht eine Write-Einheit, ein umkämpfter Key unter einer engen Schleife kostet also stetig, ohne voranzukommen. Der Preisrechner macht aus einer Schreibrate eine Monatssumme, falls du wissen willst, was ein Retry-Sturm wirklich kostet, bevor du die Versuche begrenzt.
Um diese Guards gegen deine eigenen Tabellen auszuführen, ohne die Platzhalter-Maps durch die Shell zu quoten, lade DynoTable herunter.
Verwandte Beispiele
- DynamoDB Conditional Write in Node.js — derselbe Optimistic Lock mit AWS SDK v3.
- DynamoDB Conditional Write in Python — derselbe Optimistic Lock mit boto3.
- DynamoDB PutItem mit der AWS CLI — das nur-erzeugende
attribute_not_exists-Put. - DynamoDB Condition Expressions — jede Funktion, mit Mustern.
- ReturnValues verstehen — was dir jede Return-Option liefert.
- DynamoDB ConditionalCheckFailedException — wann die fehlgeschlagene Prüfung erwartet ist und wie du sie günstig behandelst.
Referenzen
- 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
Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.