2011-08-22 26 views
194

Non sono un esperto di database e non ho conoscenze informatiche formali, quindi abbi pazienza con me. Voglio sapere i tipi di mondo reale cose negative che possono accadere se si utilizza MongoDB, che non è compatibile con ACID. Questo vale per qualsiasi database non conforme ACID.Cosa vuol dire che MongoDB non sia ACID compatibile?

Comprendo che MongoDB può eseguire Atomic Operations, ma che non "supporta il blocco tradizionale e le transazioni complesse", principalmente per motivi di prestazioni. Capisco anche l'importanza delle transazioni di database e l'esempio di quando il database è per una banca e si aggiornano diversi record che devono essere tutti sincronizzati, si desidera che la transazione ritorni allo stato iniziale se c'è un interruzione di corrente in modo di credito è uguale acquisto, ecc

Ma quando mi trovo in conversazioni su MongoDB, quelli di noi che non conoscono i dettagli tecnici di come i database sono in effetti implementate inizio gettando intorno affermazioni come:

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

Quel "non salverà correttamente" parte si riferisce a questa comprensione: Se c'è un diritto interruzione di corrente nel momento che si sta scrivendo a MongoDB, c'è una possibilità per un particolare record (dicono che stai monitorando pagine visualizzate in documenti con 10 attributi ciascuno), che uno dei documenti ha salvato solo 5 attributi ... il che significa che nel tempo i contatori di visualizzazione di pagina saranno "leggermente" disattivati. Non saprai mai da quanto, sai che saranno corretti al 99,999%, ma non al 100%. Ciò è dovuto al fatto che, a meno che non lo si sia reso esplicitamente un mongodb atomic operation, 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 dell'ACID non soddisfano e in quali circostanze e in che modo sai quando lo 0,001% dei tuoi dati è disattivato? Non può essere risolto in qualche modo? In caso contrario, questo sembra significare che non dovresti memorizzare cose come la tua tabella users in MongoDB, perché un record potrebbe non essere salvato. Ma ancora una volta, quel 1/1.000.000 di utenti potrebbe semplicemente "provare ad accedere di nuovo", no?

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

risposta

111

Una cosa che si perde con MongoDB è le transazioni con più raccolte (tabella). I modificatori atomici in MongoDB possono funzionare solo contro un singolo documento.

Se è necessario rimuovere un articolo dall'inventario e aggiungerlo all'ordine di qualcuno allo stesso tempo - non è possibile. A meno che queste due cose - inventario e ordini - non esistano nello stesso documento (cosa che probabilmente non fanno).

ho incontrato questo problema in un'applicazione Sto lavorando su e due possibili soluzioni esistono:

1) Struttura vostri documenti nel miglior modo possibile e utilizzare i modificatori atomiche nel miglior modo possibile e per lui rimanenti bit, l'uso un processo in background per pulire i record che potrebbero non essere sincronizzati. Ad esempio, rimuovo gli articoli dall'inventario e li aggiungo a un array ReservedInventory dello stesso documento utilizzando modificatori atomici.

Questo mi consente di sapere sempre che gli articoli NON sono disponibili nell'inventario (perché sono riservati a un cliente). Quando il controllo del cliente è uscito, rimuovo quindi gli articoli dall'Inventario riservato. Non è una transazione standard e dal momento che il cliente potrebbe abbandonare il carrello, ho bisogno di qualche processo in background per passare e trovare 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 alla necessità. 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 in combinazione con MongoDB. È normale usare MySQL per fornire le transazioni per le cose che ne hanno assolutamente bisogno mentre lascia che MongoDB (o qualsiasi altro NoSQL) faccia ciò che sa fare meglio.

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

+21

"* I modificatori atomici in MongoDB possono funzionare solo contro una singola raccolta *" => Penso che intendevi "contro un singolo ** documento **". – assylias

+1

Informazioni eccellenti, in genere una risposta eccellente con l'eccezione di suggerire di utilizzare MySQL. –

+0

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

31

Una buona spiegazione è contenuta in "Starbucks Does Not Use Two Phase Commit".

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 considererei che sia qualcosa che deve essere "risolto". La correzione consiste nell'utilizzare un database relazionale conforme agli ACID. Scegli un'alternativa NoSQL quando il suo comportamento soddisfa i requisiti dell'applicazione.

+1

bell'esempio mondo reale – gbn

+1

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

11

"non salverà correttamente" potrebbe significare:

  1. Per impostazione predefinita MongoDB non salva le modifiche apportate all'unità immediatamente. Quindi esiste la possibilità che tu dica a un utente che "l'aggiornamento è andato a buon fine", che si verifica un'interruzione dell'alimentazione e che l'aggiornamento va perso. MongoDB offre opzioni per controllare il livello di aggiornamento "durata". 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 anche più documenti nella stessa collezione. Nella maggior parte dei casi, non è un problema perché può essere aggirato con Two Phase Commit o ristrutturare lo schema in modo che gli aggiornamenti vengano apportati a un singolo documento. Vedi questa domanda: Document Databases: Redundant data, references, etc. (MongoDB specifically)

15

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

+0

grazie a @subGate. qualcuno là fuori che può condividere la loro esperienza con RavenDB e se effettivamente soddisfa il requisito? –

5

L'unico motivo per cui atomica modifica il lavoro rispetto a una raccolta singola è perché gli sviluppatori di mongodb hanno recentemente scambiato un blocco di database con un blocco di scrittura a livello di raccolta ampio . Decidere che l'aumento della concorrenza qui valeva il trade-off. Al suo interno, 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 farla franca con blocchi a grana molto pronunciati: eseguirai solo le operazioni in memoria mentre la mantieni, il che sarà estremamente veloce. Ciò differisce in modo significativo da un sistema di database tradizionale che a volte è costretto a eseguire I/O mantenendo una pagelock o un rowlock.

+0

potresti spiegare perché questo aumenta la concorrenza? Scusa se mi manca l'ovvio qui. – batbrat

+0

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

108

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

Qualsiasi aggiornamento per un singolo documento è

  • atomica: esso sia pienamente completata o esso non
  • Coerente: nessun lettore vedrà un "parzialmente applicata" aggiornare
  • Isolati: nuovo, no lettore vedrà una "sporca" leggere
  • durevole: (con la preoccupazione di scrittura appropriata)

Cosa MongoDB non hav e è transazioni - ovvero, aggiornamenti di più documenti che possono essere ripristinati e sono compatibili con ACID.

Si noti che è possibile creare transazioni sugli aggiornamenti ACID conformi a un singolo documento, tramite using two-phase commit.

+2

Era la risposta più chiara per me – babonk

+3

Si noti che le transazioni di commit a due fasi non sono compatibili con ACID. Per qualche ragione ho inferito il contrario finché non ho seguito il link. –

+1

C'è una domanda sulla durata di MongoDB distribuito a livello di documento, indipendentemente dalla configurazione di scrittura.Lo strumento open-source Jepsen ha scoperto che i dati possono essere persi di fronte a una partizione di rete anche con il problema di scrittura MAJORITY. Vedi l'articolo qui: http://aphyr.com/posts/284-call-me-maybe-mongodb – jrullmann

4

Per ulteriori informazioni, consultare lo ACID properties.

Anche nella documentazione MongoDB è possibile trovare uno question and answer.

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

  1. MongoDB è A Tomic su un solo 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 dell'ACID.
  2. MongoDB è C onsitent per impostazione predefinita. Tuttavia, è possibile leggere dai server secondari in un set di repliche. È possibile solo avere consistenza finale in questo caso. Questo è utile se non ti dispiace leggere dati leggermente obsoleti.
  3. MongoDB non garantisce I consolazione (sempre secondo sopra definizione):
  1. Per i sistemi con più lettori contemporanei e scrittori, MongoDB sarà consentire ai clienti di leggere i risultati di un'operazione di scrittura prima di l'operazione di scrittura restituisce.
  2. Se il mongod termina prima del commit del journal, anche se una scrittura restituisce correttamente, le query potrebbero avere dati di lettura che non esisteranno dopo il riavvio del modem.

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

  1. Per quanto riguarda D urability - è possibile configurare questo comportamento con l'opzione write concern, non è 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.

1

È possibile implementare aggiornamenti multi-chiave atomici (transazione serializzabile) sul lato client se la memoria supporta la linearizzabilità dei tasti e confrontare e impostare (che è vero per MongoDB). Questo approccio è utilizzato in Google's Percolator e nel CockroachDB ma nulla impedisce di utilizzarlo con MongoDB.

Ho creato un step-by-step visualization di tali transazioni. Spero che ti aiuterà a capirli.

Se stai bene con il livello di isolamento impegnato in lettura, allora ha senso dare un'occhiata a RAMP transactions di Peter Bailis. Possono anche essere implementati per MongoDB dal lato client.

2

A partire da MongoDB v4.0, devono essere supportate le transazioni ACID a più documenti. Attraverso l'isolamento dello snapshot, le transazioni forniranno una visione globale coerente dei dati e imporrà l'esecuzione di tutto o niente per mantenere l'integrità dei dati.

Si sentono come le transazioni dal mondo relazionale, ad es .:

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