Intermedio3 min di lettura

DynamoDB ReturnValues: ottieni l'Item vecchio o nuovo da una scrittura

Per impostazione predefinita una scrittura DynamoDB non restituisce nulla se non l'esito positivo. Ma spesso ti servono i dati intorno alla scrittura — il valore prima di averlo cambiato, o il valore aggiornato dopo. La soluzione ingenua è un secondo GetItem, che è un round trip extra e una race condition: qualcun altro può scrivere nel frattempo. DynamoDB evita entrambi con il parametro ReturnValues, che restituisce l'Item vecchio o nuovo in modo atomico come parte della scrittura stessa.

Cosa fa ReturnValues in DynamoDB?

ReturnValues indica a una scrittura DynamoDB di restituire l'Item come parte della stessa chiamata, così salti un secondo GetItem e la race condition che crea. PutItem e DeleteItem accettano NONE o ALL_OLD; UpdateItem accetta tutte e cinque le opzioni (NONE, ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW), restituendo i valori vecchi o nuovi in modo atomico.

  • ReturnValues restituisce l'Item come parte della scrittura — nessuna seconda lettura, nessuna race.
  • NONE (predefinito) — non restituisce nulla.
  • ALL_OLD — l'intero Item com'era prima della scrittura.
  • UPDATED_OLD — solo gli attributi che l'update ha cambiato, valori precedenti.
  • ALL_NEW — l'intero Item dopo la scrittura.
  • UPDATED_NEW — solo gli attributi cambiati, valori successivi.
  • PutItem/DeleteItem accettano solo NONE o ALL_OLD; UpdateItem le accetta tutte e cinque.

Il problema: ti serve il valore che hai appena sovrascritto

Supponi di gestire un help desk e che un operatore cambi lo status di un ticket da open a pending. Il tuo log di audit deve registrare qual era lo status prima del cambio. Senza ReturnValues dovresti:

  1. fare un GetItem per leggere lo status corrente,
  2. fare un UpdateItem per impostare quello nuovo.

Tra i passi 1 e 2 un altro operatore potrebbe cambiare lo status — ora il tuo log di audit registra un valore «precedente» obsoleto. Peggio ancora, sono due chiamate per un'unica operazione logica. ReturnValues la condensa in un unico UpdateItem atomico che restituisce il vecchio status com'era effettivamente al momento della scrittura.

Le cinque opzioni, e quando usare ciascuna

UpdateItem supporta l'intero set; la scelta è quale porzione dell'Item e quale lato della scrittura ti serve:

ReturnValuesRestituisceUsala quando
NONEnullanon ti serve l'Item indietro (predefinito)
ALL_OLDintero Item, pre-scritturaaudit / «cosa ho appena sostituito?»
UPDATED_OLDattributi cambiati, pre-scritturati interessano solo i campi che hai toccato
ALL_NEWintero Item, post-scritturati serve l'Item completo aggiornato da restituire a un chiamante
UPDATED_NEWattributi cambiati, post-scritturarileggere un contatore/valore che hai appena incrementato

UPDATED_NEW è l'eroe di tutti i giorni: incrementa un contatore con una update expression e rileggi il nuovo totale nella stessa chiamata, senza race. Per l'audit del ticket di supporto, ALL_OLD (o UPDATED_OLD se registri solo il campo status) cattura lo stato pre-cambio in modo atomico.

Nota l'asimmetria: PutItem e DeleteItem supportano solo NONE e ALL_OLD — non c'è un valore «nuovo» da restituire per un delete, e il valore nuovo di un put è semplicemente ciò che hai inviato. Solo UpdateItem, che muta sul posto, le offre tutte e cinque. AWS documenta la matrice esatta.

Scrivere l'update in DynoTable

Assembla l'UpdateItem e la sua update expression in modo visivo con il generatore di espressioni DynamoDB — emette la clausola SET/ADD più le mappe dei nomi e dei valori degli attributi. Nell'app, DynoTable mostra l'Item risultante dopo che una scrittura in staging è stata committata, così vedi direttamente il nuovo stato.

Revisione di una modifica in staging di un Item in DynoTable — i valori vecchi e nuovi prima che l'aggiornamento venga committato.
Revisione di una modifica in staging di un Item in DynoTable — i valori vecchi e nuovi prima che l'aggiornamento venga committato.

Trappole e prossimi passi

  • Non fare GetItem-poi-scrittura per leggere intorno a un cambio — è un round trip e una race; usa ReturnValues.
  • UPDATED_* restituisce solo gli attributi toccati — se ti serve l'intero Item, usa ALL_*.
  • PutItem/DeleteItem non possono restituire valori nuovi — solo NONE/ALL_OLD.
  • ReturnValues non sostituisce una condizione — per proteggere una scrittura, aggiungi una condition expression; per rileggerne l'effetto, usa ReturnValues. Si combinano.
  • Correlati: update expression, contatori atomici.

Vuoi fare modifiche e vedere il prima/dopo senza programmare due chiamate? Scarica DynoTable e modifica i tuoi Item direttamente.

Aggiornato