L'uso di applicazioni in tempo reale e dispositivi Internet delle cose (IoT), oltre alla crescita esponenziale degli asset di dati non strutturati, ha spinto un numero sempre maggiore di organizzazioni a passare ai database NoSQL. Infatti, si prevede che il mercato NoSQL raggiungerà i 74,5 miliardi di dollari entro il 2032, registrando un tasso di crescita (CAGR) del 24,9% dal 2024 al 2032 (gruppo IMARC, 2024).
Questa crescita non sorprende, data la capacità dei sistemi di gestione dei database (DBMS) NoSQL di gestire efficacemente set di dati ampi e diversificati e la relativa analisi dei big data richiesta. Tuttavia, molti credono ancora che i DBMS NoSQL non siano in grado di soddisfare un requisito fondamentale di molte organizzazioni: la gestione delle transazioni ACID e la conformità. La buona notizia è che alcuni DBMS NoSQL possono farlo.
In questo articolo parleremo di cosa sono le transazioni ACID, delle proprietà delle transazioni ACID, del perché queste transazioni sono importanti e di un esempio di transazione ACID in un DBMS NoSQL.
Sommario
A un livello base, le transazioni del database sono un insieme di operazioni di lettura e scrittura sul database che sono state completate con successo in base alle definizioni del DBMS (ad esempio, criteri di transazione definiti). Esistono due tipi principali di transazioni:
Transazioni singole: una transazione singola è una serie di una o più operazioni di database che si traducono in un'unica azione, completata con successo. Una volta completata, la transazione viene accettata e può essere consultata nel log delle transazioni. Un esempio comune di transazione singola è il prelievo di denaro da uno sportello bancomat.
Multi-transazioni: una multi-transazione, talvolta chiamata transazione distribuita, è composta da più transazioni interdipendenti distribuite su diversi database e sistemi (ad esempio, sistemi distribuiti). I record di queste transazioni si trovano anche in un log delle transazioni. Un esempio di queste transazioni include il trasferimento di denaro da un conto all'altro o il rilascio di un badge di sicurezza con foto a un nuovo dipendente.
È importante notare che alcune transazioni devono rispettare rigorosi standard di integrità dei dati (ad esempio, i dati devono essere completi e corretti) e di coerenza dei dati (ad esempio, il valore deve essere lo stesso in tutte le tabelle/database). Questo è spesso il caso in cui è coinvolta la responsabilità fiduciaria o la conformità normativa. Gli esempi includono banche commerciali, intermediazione di investimenti e accordi legali. In queste situazioni, un'aderenza standard alle definizioni DBMS non è sufficiente e sono richieste transazioni ACID.
ACID è un acronimo che sta per atomicity, consistency, isolation, and durability (ACID), ovvero atomicità, coerenza, isolamento e durabilità. Insieme, le proprietà ACID assicurano che un insieme di operazioni del database (raggruppate in una transazione) lascino il database in uno stato valido anche in caso di errori imprevisti. Inoltre, le transazioni ACID forniscono il livello di garanzie transazionali che molti enti di regolamentazione richiedono.
Di seguito è riportata una panoramica generale di ogni elemento di una transazione ACID, nonché una descrizione di come un database di documenti NoSQL è in grado di gestire tale elemento ACID. Ai fini di questo articolo, verrà utilizzato MongoDB Atlas .
L'atomicità garantisce che tutti i comandi che compongono una transazione siano trattati come un'unica unità e che siano completati, con successo o meno, nel loro insieme. Questo è importante in caso di guasto del sistema o di interruzione dell'alimentazione, in quanto se una transazione non è stata elaborata completamente, verrà scartata e il database manterrà l'integrità dei dati.
in MongoDB, un'operazione di scrittura è atomica a livello di un singolo documento, anche se l'operazione modifica più documenti incorporati all'interno di un singolo documento. Per le situazioni che richiedono l'atomicità delle operazioni di lettura e scrittura su più documenti (in una singola collection o in più collection), MongoDB supporta transazioni distribuite, comprese le transazioni su replica set e sharded cluster.
La coerenza garantisce che le modifiche apportate all'interno di una transazione siano propagate in tutto il sistema di database (ad esempio, i nodi) e rispettino i vincoli del DBMS. Se la coerenza dei dati rischia di essere compromessa a causa di una transazione in uno stato incoerente, l'intera transazione verrà annullata.
Come MongoDB gestisce la coerenza:MongoDB offre la flessibilità di normalizzare o duplicare i dati per ottimizzare le applicazioni. Se i dati sono duplicati nello schema, lo sviluppatore deve decidere come mantenere coerenti i dati duplicati in più collection. Alcune applicazioni richiedono che i dati duplicati siano resi coerenti immediatamente, mentre altre applicazioni possono tollerare la lettura di dati non aggiornati. Di seguito sono illustrati alcuni esempi:
Nota: Scopri di più sulla coerenza dei dati.
Ogni transazione è isolata dalle altre transazioni per evitare conflitti di dati. Ciò semplifica anche le operazioni del database in relazione alla gestione di più voci e transazioni multilivello. Ad esempio, se due utenti stanno cercando di modificare gli stessi dati (o anche la stessa transazione), il DBMS utilizza un meccanismo chiamato lock manager per sospendere gli altri utenti fino al completamento delle modifiche apportate dal primo utente.
MongoDB utilizza una tecnica chiamata snapshot isolation (ad esempio, ogni transazione sembra operare su uno snapshot personale del database creato all'inizio della transazione). Le transazioni possono leggere i dati dallo “snapshot“ dei dati confermati al momento dell'inizio della transazione, e qualsiasi aggiornamento in conflitto causerà l'annullamento della transazione.
Inoltre, le transazioni MongoDB supportano un livello di controllo sulla modalità di lettura a livello di transazione e modalità di scrittura a livello di transazione. I client possono impostare un livello appropriato di controllo per le operazioni di lettura e scrittura, con il livello più rigoroso che combina lo snapshot read concern con il majority write concern. Il majority write concern significa che le operazioni di scrittura sono state definitivamente confermate nella maggioranza calcolata dei nodi che contengono i dati (configurabile dallo sviluppatore).
La durabilità garantisce che, una volta completata la transazione e scritte le modifiche nel database, queste vengano mantenute. Questo assicura che i dati all'interno del sistema rimangano salvati anche in caso di guasti al sistema, come arresti improvvisi o interruzioni di corrente. Il concetto di durabilità è un elemento chiave dell'affidabilità dei dati.
MongoDB crea un OPLog contenente la posizione del disco e i byte modificati per ogni “scrittura“. Se si verifica un evento imprevisto (ad esempio un'interruzione di corrente) durante la scrittura della transazione, l'OPlog può essere utilizzato al riavvio del sistema per ripetere le scritture che non sono state salvate su disco prima dello spegnimento. Inoltre, le operazioni vengono modificate prima di essere scritte nell'OpLog in modo che siano idempotenti e possano essere ripetute più volte. Per impostazione predefinita, le transazioni, o “scritture“, vengono salvate su disco ogni 60 secondi circa.
Le transazioni ACID aiutano a mantenere l'integrità e l'affidabilità dei dati, garantendo al contempo che i dati vitali soggetti a normative governative o di settore (ad esempio, conto bancario, portafoglio azionario) soddisfino gli standard richiesti. Inoltre, la conformità all'ACID è spesso un prerequisito per implementare la replica dei dati e ottenere un'elevata disponibilità nei sistemi di database distribuiti.
Utilizzando il database di documenti NoSQL MongoDB Atlas, ecco un esempio di come vengono gestite le transazioni ACID con più documenti e di come le transazioni ACID garantiscono l'allineamento agli standard minimi delle proprietà ACID.
Immagina di creare una funzione per trasferire denaro da un conto bancario a un altro, in cui ogni conto rappresenta un record a sé stante. Se il denaro viene prelevato con successo dal conto di origine ma non viene mai accreditato sul conto di destinazione, si è creato un grave problema contabile. Al contrario, se il conto di destinazione viene accreditato ma il conto di origine non viene mai addebitato, si verifica un altro grave problema contabile.
Il diagramma mostra come le proprietà ACID influiscono sul flusso di trasferimento di denaro da un conto bancario a un altro.
Queste due operazioni di scrittura devono avvenire o non avvenire entrambe per mantenere il sistema e i suoi dati coerenti. Inoltre, ciò significa che se un comando della transazione fallisce, il database deve eseguire il rollback (ad esempio, annullare) di tutte le modifiche scritte nel corso della transazione.
Nota: Per maggiori informazioni, visita il repository GitHub Quick Start Node.js per ottenere una copia dell'esempio di codice completo ed eseguirlo direttamente.
Quando si gestiscono transazioni multi-documento in un sistema distribuito, è importante ricordare che esiste un impatto dovuto al sovraccarico delle prestazioni, che potrebbe influire sui vincoli delle risorse e sugli obiettivi di prestazioni. Inoltre, poiché il database deve “bloccare“ le risorse coinvolte per evitare che le scritture simultanee interferiscano tra loro (ad esempio, in caso di fallimento della transazione), altri client che tentano di scrivere dati potrebbero rimanere bloccati in attesa del completamento della transazione, il che può influire sulla latenza dell'applicazione e sull'esperienza utente.
Il document model di MongoDB consente di archiviare i dati correlati in un unico documento. Il modello di documento, combinato con gli aggiornamenti atomici dei documenti, elimina la necessità di transazioni nella maggior parte dei casi d'uso. Tuttavia, ci sono casi in cui le transazioni MongoDB multi-documento e multi-collection rappresentano la scelta migliore.
Le transazioni MongoDB funzionano in modo simile alle transazioni in altri database. Per utilizzare una transazione, avvia una sessione MongoDB tramite un driver. Quindi, utilizza quella sessione per eseguire il tuo gruppo di operazioni sul database. È possibile eseguire qualsiasi operazione CRUD (creazione, lettura, aggiornamento ed eliminazione) su più documenti, collection e shard.
Per esempi di codice specifici su come implementare le transazioni, consulta le guide rapide sul Centro per sviluppatori di MongoDB:
Consulta la documentazione dei MongoDB drivers per le guide specifiche per ciascuno dei linguaggi ufficialmente supportati da MongoDB. Puoi anche visualizzare un elenco delle best practice sulle transazioni e delle considerazioni sulla produzione.
Le applicazioni che richiedono transazioni solitamente presentano casi d'uso in cui i valori vengono scambiati tra diverse parti. Si tratta in genere di applicazioni "System of Record " o "Line of Business ".
Esempi di applicazioni che possono trarre vantaggio dalle transazioni multi-documento includono:
Sistemi che trasferiscono fondi da un conto all'altro (ad esempio, applicazioni bancarie, sistemi di elaborazione dei pagamenti, piattaforme di trading).
Sistemi di prenotazione e di supply chain in cui la proprietà di beni e servizi viene trasferita da una parte all'altra.
Sistemi di fatturazione che archiviano le informazioni in record dettagliati e in record di riepilogo.
In generale, si consiglia di modellare i dati in modo che i dati a cui si accede insieme siano archiviati insieme. Quando i dati vengono modellati in questo modo, non solo si ottengono prestazioni migliori, ma si elimina anche la necessità delle transazioni.
Per le applicazioni che richiedono transazioni, le best practice a cui attenersi sono le seguenti:
Suddividere le transazioni di lunga durata in parti più piccole in modo che non superino il timeout predefinito di 60 secondi. (Da notare che questo timeout può essere esteso.) Assicurarsi che le operazioni nelle transazioni utilizzino indici in modo da essere eseguite rapidamente.
Limitare ogni transazione a 1.000 modifiche di documenti.
Assicurarsi che i livelli di controllo appropriati per le modalità di lettura e scrittura sono configurati (tieni presente che a partire dalla versione 5.0, MongoDB utilizza per impostazione predefinita il majority write concern necessario).
Aggiungere una gestione appropriata degli errori e riprovare a effettuare le transazioni che falliscono a causa di errori temporanei.
Ricordare il costo in termini di prestazioni delle transazioni che coinvolgono più shard. Per maggiori informazioni su queste best practice, consulta il white paper Transazioni ACID multi-documento su MongoDB e la documentazione MongoDB sulle transazioni.
Vuoi saperne di più? MongoDB Atlas è il database as a service completamente gestito di MongoDB ed è il modo più semplice per iniziare a utilizzare MongoDB. Inizia con le transazioni creando un MongoDB Atlas cluster gratuito.