Cosa significava MongoDB non conforme ACID prima della v4?


226

Non sono un esperto di database e non ho una formazione informatica formale, quindi abbiate pazienza. Voglio sapere i tipi di cose negative del mondo reale che possono accadere se si utilizza una vecchia versione MongoDB precedente alla v4 , che non erano compatibili con ACID . Questo vale per qualsiasi database ACID non conforme.

Comprendo che MongoDB può eseguire operazioni atomiche , ma che non "supportano il blocco tradizionale e le transazioni complesse", principalmente per motivi di prestazioni. Comprendo anche l'importanza delle transazioni del database e l'esempio di quando il database è per una banca e stai aggiornando diversi record che devono essere tutti sincronizzati, vuoi che la transazione torni allo stato iniziale se c'è un interruzione di corrente in modo che il credito sia uguale all'acquisto, ecc.

Ma quando entro in conversazioni su MongoDB, quelli di noi che non conoscono i dettagli tecnici su come i database sono effettivamente implementati iniziano a lanciare dichiarazioni come:

MongoDB è molto più veloce di MySQL e Postgres, ma c'è una piccola possibilità, come 1 su un milione, che "non salverà correttamente".

Quella parte "non si salva correttamente" si riferisce a questa comprensione: se c'è un'interruzione di corrente nel momento in cui stai scrivendo su MongoDB, c'è la possibilità di un particolare record (supponi che stai monitorando le visualizzazioni di pagina in documenti con 10 attributi ciascuno), che uno dei documenti ha salvato solo 5 degli attributi ... il che significa che nel tempo i contatori delle visualizzazioni di pagina saranno "leggermente" disattivati. Non saprai mai di quanto, sai che saranno corretti al 99,999%, ma non al 100%. Questo perché, a meno che non sia stata specificatamente effettuata un'operazione atomica mongodb , non è garantito che l'operazione sia stata atomica.

Quindi la mia domanda è: qual è l'interpretazione corretta di quando e perché MongoDB potrebbe non "salvare correttamente"? Quali parti di ACID non soddisfano e in quali circostanze e come si fa a sapere quando lo 0,001% dei dati è spento? Non può essere risolto in qualche modo? Altrimenti, questo sembra significare che non dovresti archiviare cose come la tua userstabella in MongoDB, perché un record potrebbe non essere salvato. Ma ancora una volta, quell'utente 1 / 1.000.000 potrebbe aver bisogno di "provare a registrarsi di nuovo", no?

Sto solo cercando un elenco di quando / perché accadono cose negative con un database ACID non conforme come MongoDB, e idealmente se esiste una soluzione standard (come eseguire un processo in background per pulire i dati o usare solo SQL per questo, ecc.) .

Risposte:


133

Una cosa che perdi con MongoDB sono le transazioni multi-collezione (tabella). I modificatori atomici in MongoDB possono funzionare solo con un singolo documento.

Se devi rimuovere un articolo dall'inventario e aggiungerlo contemporaneamente all'ordine di qualcuno, non puoi. A meno che queste due cose - inventario e ordini - esistano nello stesso documento (che probabilmente non lo fanno).

Ho riscontrato questo stesso problema in un'applicazione a cui sto lavorando e avevo due possibili soluzioni tra cui scegliere:

1) Strutturare i documenti nel miglior modo possibile e utilizzare modificatori atomici nel miglior modo possibile e, per il resto, utilizzare un processo in background per ripulire i record che potrebbero non essere sincronizzati. Ad esempio, rimuovo gli articoli dall'inventario e li aggiungo a un array riservatoInventory dello stesso documento utilizzando modificatori atomici.

Questo mi fa sempre sapere che gli articoli NON sono disponibili nell'inventario (perché sono riservati da un cliente). Quando il cliente effettua il check out, rimuovo gli articoli dall'inventario riservato. Non è una transazione standard e poiché il cliente potrebbe abbandonare il carrello, ho bisogno di alcuni processi in background per passare e trovare i carrelli abbandonati e spostare l'inventario riservato nel pool di inventario disponibile.

Questo è ovviamente meno che ideale, ma è l'unica parte di una grande applicazione in cui mongodb non si adatta perfettamente all'esigenza. Inoltre, funziona perfettamente fino ad ora. Questo potrebbe non essere possibile per molti scenari, ma a causa della struttura del documento che sto usando, si adatta bene.

2) Utilizzare un database transazionale insieme a MongoDB. È comune usare MySQL per fornire transazioni per le cose che ne hanno assolutamente bisogno lasciando che MongoDB (o qualsiasi altro NoSQL) faccia ciò che fa meglio.

Se la mia soluzione n. 1 non funziona a lungo termine, approfondirò ulteriormente la combinazione di MongoDB con MySQL, ma per ora il n. 1 soddisfa bene le mie esigenze.


27
"I modificatori atomici in MongoDB possono funzionare solo contro una singola raccolta " => Penso che tu intendessi "contro un singolo documento ".
assylias,

2
Informazioni eccellenti, in genere un'ottima risposta con l'eccezione di suggerire di usare MySQL.
Doug Molineux,

״ Una cosa che perdi con MongoDB sono le transazioni multi-collezione (tabella). I modificatori atomici in MongoDB possono funzionare solo su un singolo documento ״ di mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): "In MongoDB, un'operazione di scrittura è atomica a livello di singolo documento, anche se l'operazione modifica più documenti incorporati all'interno di un singolo documento. "
yoav.str,

5
La mancanza di transazioni ACID multi-documento non è più il caso. MongoDB ha annunciato che arriveranno nella versione 4.0. Vedi mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik

1
Per ora, poiché MongoDB 4.0 è conforme ACID mongodb.com/transactions con transazioni multi-documento. Dai
Ratah,

134

In realtà non è corretto che MongoDB non sia compatibile ACID. Al contrario, MongoDB è compilatore ACID a livello di documento .

Qualsiasi aggiornamento a un singolo documento è

  • Atomico: o completa completamente o no
  • Coerente: nessun lettore vedrà un aggiornamento "parzialmente applicato"
  • Isolato: di nuovo, nessun lettore vedrà una lettura "sporca"
  • Durevole: (con l'appropriata preoccupazione di scrittura)

Ciò che MongoDB non ha sono le transazioni , ovvero aggiornamenti di più documenti che possono essere sottoposti a rollback e conformi all'ACID.

Si noti che è possibile creare transazioni in cima agli aggiornamenti conformi ACID a un singolo documento, utilizzando il commit in due fasi .


3
Si noti che le transazioni di commit a due fasi non sono conformi all'ACID. Per qualche ragione ho dedotto il contrario fino a quando non ho seguito il link.
Giustino C,

1
C'è qualche domanda sulla durata del MongoDB distribuito a livello di documento, indipendentemente dalla configurazione relativa alla scrittura. Lo strumento open source Jepsen ha scoperto che i dati possono essere persi di fronte a una partizione di rete anche con la preoccupazione di scrittura MAJORITY. Vedi il commento
jrullmann

9
Avere ACID a livello di un singolo documento che in qualche modo equivale a un singolo record in RDBMS non è utile in molti casi. Il termine della transazione non si riferisce alla singola tabella e puoi persino avere un meccanismo di commit in due fasi e coinvolgere più XAResource, quindi riferirsi al singolo documento come conforme ACID è alquanto problematico, IMHO.
Yair Zaslavsky,

5
D'accordo con Yair. "Conformità ACID a livello di documento" non è un punto di forza. Fondamentalmente significa semplicemente "non conforme ACID". ACID non è mai stato pensato per "solo una riga / documento / entità". Si tratta di mantenere i dati coerenti in tutto il database.
joshua.paling,

34

Una buona spiegazione è contenuta in "Starbucks non usa il commit in due fasi" .

Non si tratta di database NoSQL, ma illustra il punto che a volte puoi permetterti di perdere una transazione o di avere temporaneamente il tuo database in uno stato incoerente.

Non lo considero qualcosa che deve essere "riparato". La correzione consiste nell'utilizzare un database relazionale conforme ACID. Scegli un'alternativa NoSQL quando il suo comportamento soddisfa i requisiti della tua applicazione.


1
Come ogni analogia ha i suoi limiti. Nel software, è facile creare nuovi array [cassieri] e farli elaborare transazioni sincrone ciascuno, mentre il costo del mondo reale sarebbe ridicolmente costoso.
HRJ,

16

Penso che altre persone abbiano già dato buone risposte. Tuttavia, vorrei aggiungere che ci sono DB ACID NOSQL (come http://ravendb.net/ ). Quindi non è solo una decisione NOSQL - nessun ACID vs Relazionale con ACID ....


1
grazie @subGate. qualcuno là fuori che può condividere la propria esperienza con ravenDB e se soddisfa davvero il requisito?
Nir Pengas,

12

"non verrà salvato correttamente" potrebbe significare:

  1. Per impostazione predefinita MongoDB non salva immediatamente le modifiche sull'unità. Quindi c'è la possibilità che tu dica a un utente che "l'aggiornamento è andato a buon fine", che si verifica un'interruzione di corrente e l'aggiornamento viene perso. MongoDB fornisce opzioni per controllare il livello di "durabilità" degli aggiornamenti. Può attendere che le altre repliche ricevano questo aggiornamento (in memoria), attendere che la scrittura avvenga sul file journal locale, ecc.

  2. Non ci sono facili aggiornamenti "atomici" a più raccolte e persino a più documenti nella stessa raccolta. Nella maggior parte dei casi non è un problema perché può essere aggirato con Two Phase Commit o ristrutturando lo schema in modo che gli aggiornamenti vengano effettuati su un singolo documento. Vedi questa domanda: Database di documenti: dati ridondanti, riferimenti, ecc. (In particolare MongoDB)


10

A partire da MongoDB v4.0, le transazioni ACID multi-documento devono essere supportate. Attraverso l'isolamento dello snapshot, le transazioni forniranno una visione coerente a livello globale dei dati e imporranno l'esecuzione totale o nulla per mantenere l'integrità dei dati.

Si sentono come transazioni dal mondo relazionale, ad esempio:

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

Vedi https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb


È uscita la prima release candidate di MongoDB4.0 - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik

5

Si prega di leggere le proprietà ACID per ottenere una migliore comprensione.

Inoltre nella documentazione MongoDB è possibile trovare una domanda e una risposta .

MongoDB non è conforme ACID. Leggi di seguito per una discussione sulla conformità ACID.

  1. MongoDB è Atomico solo a livello di documento. Non è conforme alla definizione di atomico che conosciamo dai sistemi di database relazionali, in particolare il link sopra. In questo senso MongoDB non è conforme alla A di ACID.
  2. MongoDB è Consitent per impostazione predefinita. Tuttavia, è possibile leggere da server secondari in un set di repliche. In questo caso puoi solo avere coerenza . Questo è utile se non ti dispiace leggere dati leggermente obsoleti.
  3. MongoDB non garantisce la Isolation (sempre secondo la definizione sopra):
  1. Per i sistemi con più lettori e scrittori simultanei, MongoDB consentirà ai client di leggere i risultati di un'operazione di scrittura prima che l'operazione di scrittura ritorni.
  2. Se il mongod termina prima del commit del journal, anche se una scrittura ritorna correttamente, le query potrebbero avere dati di lettura che non esisteranno dopo il riavvio del mongod.

Tuttavia , MongoDB modifica ogni documento separatamente (per inserimenti e aggiornamenti); solo a livello di documento, non su transazioni multi-documento.

  1. Per quanto riguarda l' Durabilità, è possibile configurare questo comportamento con l' write concernopzione, non sono sicuro però. Forse qualcuno lo sa meglio.

Credo che alcune ricerche siano in corso per spostare NoSQL verso vincoli ACID o simili. Questa è una sfida perché i database NoSQL sono in genere veloci (er) e i vincoli ACID possono rallentare significativamente le prestazioni.


4

L'unico motivo per cui atomic modifica il lavoro rispetto a una raccolta singola è perché gli sviluppatori di mongodb hanno recentemente scambiato un blocco del database con un blocco di scrittura a livello di raccolta. Decidere che l'aumento della concorrenza qui valeva il compromesso. Fondamentalmente, mongodb è un file mappato in memoria: hanno delegato la gestione del pool di buffer al sottosistema VM della macchina. Poiché è sempre in memoria, sono in grado di cavarsela con blocchi molto complicati: eseguirai solo operazioni in memoria mentre lo tieni, che sarà estremamente veloce. Ciò differisce in modo significativo da un sistema di database tradizionale che a volte è costretto a eseguire operazioni di I / O mentre si tiene un pagelock o un rowlock.


potresti spiegare perché questo aumenta la concorrenza? Scusami se mi manca l'ovvio qui.
Batbrat,

@batbrat: considera due client che tentano di scrivere simultaneamente in raccolte diverse nello stesso database. Con un blocco del database, uno dei client dovrà attendere che l'altro finisca prima che possa avvenire la sua scrittura. Con un blocco raccolta entrambi i client possono scrivere contemporaneamente. Questo è ciò che si intende per maggiore concorrenza. Naturalmente, se entrambi i client tentano di scrivere nella stessa raccolta, si dovrà attendere.
jrullmann,

2

"In MongoDB, un'operazione su un singolo documento è atomica" - Questo è il passato

Nella nuova versione di MongoDB 4.0 PUOI:

Tuttavia, per le situazioni che richiedono atomicità per gli aggiornamenti di più documenti o la coerenza tra le letture di più documenti, MongoDB offre la possibilità di eseguire transazioni multi-documento su set di repliche. Le transazioni multi-documento possono essere utilizzate su più operazioni, raccolte, database e documenti. Le transazioni multi-documento forniscono una proposta "tutto o niente". Quando si effettua il commit di una transazione, tutte le modifiche ai dati effettuate nella transazione vengono salvate. Se qualsiasi operazione nella transazione fallisce, la transazione si interrompe e tutte le modifiche ai dati effettuate nella transazione vengono eliminate senza diventare mai visibili. Finché non viene eseguito il commit di una transazione, al di fuori della transazione non sono visibili operazioni di scrittura nella transazione.

Sebbene ci siano alcune limitazioni su come e quali operazioni possono essere eseguite.

Controlla il documento Mongo. https://docs.mongodb.com/master/core/transactions/


1

È possibile implementare gli aggiornamenti atomici multi-chiave (transazione serializzabile) sul lato client se lo spazio di archiviazione supporta la linearizzabilità delle chiavi e il confronto e l'impostazione (che è vero per MongoDB). Questo approccio è utilizzato in Google Percolator e in CockroachDB ma nulla ti impedisce di usarlo con MongoDB.

Ho creato una visualizzazione dettagliata di tali transazioni. Spero che ti possa aiutare a capirli.

Se stai bene con il livello di isolamento impegnato nella lettura, ha senso dare un'occhiata alle transazioni RAMP di Peter Bailis. Possono anche essere implementati per MongoDB sul lato client.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.