Was bedeutete es wirklich, dass MongoDB vor v4 nicht ACID-konform war?

226

Ich bin kein Datenbankexperte und habe keinen formalen Hintergrund in der Informatik. Ich möchte wissen, welche negativen Dinge in der realen Welt passieren können, wenn Sie eine alte MongoDB-Version vor Version 4 verwenden , die nicht ACID- konform war. Dies gilt für alle nicht ACID-konformen Datenbanken.

Ich verstehe, dass MongoDB Atomic Operations ausführen kann , aber dass sie "traditionelle Sperren und komplexe Transaktionen nicht unterstützen", hauptsächlich aus Leistungsgründen. Ich verstehe auch die Bedeutung von Datenbanktransaktionen und das Beispiel, wenn Ihre Datenbank für eine Bank bestimmt ist und Sie mehrere Datensätze aktualisieren, die alle synchron sein müssen. Sie möchten, dass die Transaktion in den Ausgangszustand zurückkehrt, wenn es eine gibt Stromausfall, also Kredit gleich Kauf usw.

Aber wenn ich in Gespräche über MongoDB gerate, werfen diejenigen von uns, die die technischen Details der tatsächlichen Implementierung von Datenbanken nicht kennen, Aussagen wie:

MongoDB ist viel schneller als MySQL und Postgres, aber es gibt eine winzige Chance, wie 1 zu 1 Million, dass es "nicht richtig speichert".

Dieser Teil "wird nicht richtig gespeichert" bezieht sich auf dieses Verständnis: Wenn zum Zeitpunkt des Schreibens in MongoDB ein Stromausfall auftritt, besteht die Möglichkeit eines bestimmten Datensatzes (z. B. verfolgen Sie Seitenaufrufe in Dokumenten mit 10 Attributen jeweils), dass eines der Dokumente nur 5 der Attribute gespeichert hat… was bedeutet, dass Ihre Seitenaufrufzähler im Laufe der Zeit "leicht" abweichen werden. Sie werden nie wissen, um wie viel, Sie wissen, dass sie zu 99,999% korrekt sind, aber nicht zu 100%. Dies liegt daran, dass die Operation nicht garantiert atomar ist, es sei denn, Sie haben dies ausdrücklich zu einer Mongodb-Atomoperation gemacht .

Meine Frage ist also, was ist die richtige Interpretation von wann und warum MongoDB möglicherweise nicht "richtig speichert"? Welche Teile von ACID erfüllen es nicht und unter welchen Umständen und woher wissen Sie, wann diese 0,001% Ihrer Daten deaktiviert sind? Kann das nicht irgendwie behoben werden? Wenn nicht, scheint dies zu bedeuten, dass Sie Dinge wie Ihre usersTabelle nicht in MongoDB speichern sollten , da ein Datensatz möglicherweise nicht gespeichert wird . Aber andererseits muss dieser 1 / 1.000.000-Benutzer möglicherweise nur "erneut versuchen, sich anzumelden", nein?

Ich suche nur nach einer Liste, wann / warum bei einer nicht mit ACID nicht kompatiblen Datenbank wie MongoDB negative Dinge passieren, und im Idealfall, wenn es eine Standardumgehung gibt (z. B. einen Hintergrundjob ausführen, um Daten zu bereinigen, oder nur SQL dafür verwenden usw.). .

Lance Pollard
quelle

Antworten:

133

Eine Sache, die Sie mit MongoDB verlieren, sind Transaktionen mit mehreren Sammlungen (Tabellen). Atomic Modifikatoren in MongoDB können nur für ein einzelnes Dokument verwendet werden.

Wenn Sie einen Artikel aus dem Inventar entfernen und gleichzeitig zur Bestellung einer anderen Person hinzufügen müssen, können Sie dies nicht. Es sei denn, diese beiden Dinge - Inventar und Bestellungen - befinden sich im selben Dokument (was sie wahrscheinlich nicht tun).

Ich bin in einer Anwendung, an der ich arbeite, auf dasselbe Problem gestoßen und hatte zwei mögliche Lösungen zur Auswahl:

1) Strukturieren Sie Ihre Dokumente so gut wie möglich und verwenden Sie atomare Modifikatoren so gut Sie können. Verwenden Sie für das verbleibende Bit einen Hintergrundprozess, um Datensätze zu bereinigen, die möglicherweise nicht synchron sind. Zum Beispiel entferne ich Elemente aus dem Inventar und füge sie mithilfe atomarer Modifikatoren einem reservierten Inventar-Array desselben Dokuments hinzu.

Dadurch weiß ich immer, dass Artikel NICHT im Inventar verfügbar sind (da sie von einem Kunden reserviert wurden). Wenn der Kunde auscheckt, entferne ich die Artikel aus dem reservierten Inventar. Es ist keine Standardtransaktion, und da der Kunde den Warenkorb verlassen könnte, benötige ich einen Hintergrundprozess, um verlassene Warenkörbe zu finden und das reservierte Inventar wieder in den verfügbaren Inventarpool zu verschieben.

Dies ist offensichtlich weniger als ideal, aber es ist der einzige Teil einer großen Anwendung, bei der Mongodb nicht perfekt zu den Anforderungen passt. Außerdem funktioniert es bisher einwandfrei. Dies ist in vielen Szenarien möglicherweise nicht möglich, passt aber aufgrund der von mir verwendeten Dokumentstruktur gut.

2) Verwenden Sie eine Transaktionsdatenbank in Verbindung mit MongoDB. Es ist üblich, MySQL zu verwenden, um Transaktionen für die Dinge bereitzustellen, die sie unbedingt benötigen, während MongoDB (oder jedes andere NoSQL) das tun kann, was es am besten kann.

Wenn meine Lösung von # 1 auf lange Sicht nicht funktioniert, werde ich weiter untersuchen, wie MongoDB mit MySQL kombiniert werden kann, aber # 1 passt vorerst gut zu meinen Anforderungen.

Bryan Migliorisi
quelle
27
" Atomic Modifiers in MongoDB können nur gegen eine einzelne Sammlung arbeiten " => Ich denke, Sie meinten "gegen ein einzelnes Dokument ".
Assylias
2
Hervorragende Informationen, im Allgemeinen eine ausgezeichnete Antwort, mit Ausnahme des Vorschlags, MySQL zu verwenden.
Doug Molineux
״ Eine Sache, die Sie mit MongoDB verlieren, sind Transaktionen mit mehreren Sammlungen (Tabellen). Atommodifikatoren in MongoDB können nur gegen ein einzelnes Dokument ״ aus mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ) arbeiten: "In MongoDB ist eine Schreiboperation auf der Ebene eines einzelnen atomar Dokument, auch wenn der Vorgang mehrere eingebettete Dokumente in einem einzelnen Dokument ändert. "
yoav.str
5
Das Fehlen von ACID-Transaktionen mit mehreren Dokumenten ist nicht mehr der Fall. MongoDB kündigte an, dass sie in Version 4.0 kommen. Siehe mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik
1
Da MongoDB 4.0 ACID-konform ist, ist mongodb.com/transactions mit Transaktionen mit mehreren Dokumenten verfügbar . Werfen
Ratah
134

Es ist eigentlich nicht richtig, dass MongoDB nicht ACID-konform ist. Im Gegenteil, MongoDB ist auf Dokumentebene ACID-kompatibel .

Jede Aktualisierung eines einzelnen Dokuments ist

  • Atomic: Es ist entweder vollständig abgeschlossen oder nicht
  • Konsistent: Kein Leser sieht ein "teilweise angewendetes" Update
  • Isoliert: Auch hier wird kein Leser einen "schmutzigen" Lesevorgang sehen
  • Langlebig: (mit dem entsprechenden Schreibproblem)

Was MongoDB nicht hat, sind Transaktionen , dh Aktualisierungen mehrerer Dokumente, die zurückgesetzt werden können und ACID-konform sind.

Beachten Sie, dass Sie Transaktionen mithilfe der zweiphasigen Festschreibung zusätzlich zu den ACID-kompatiblen Aktualisierungen eines einzelnen Dokuments erstellen können .

William Z.
quelle
3
Beachten Sie, dass die Transaktionen von zweiphasigen Commits nicht ACID-konform sind. Aus irgendeinem Grund folgerte ich das Gegenteil, bis ich dem Link folgte.
Justin C
1
Es gibt einige Fragen zur Haltbarkeit von verteilter MongoDB auf Dokumentebene, unabhängig von der Konfiguration des Schreibproblems. Das Open-Source-Tool Jepsen stellte fest, dass Daten trotz einer MAJORITY-Schreibbedenken angesichts einer Netzwerkpartition verloren gehen können. Siehe den Artikel
jrullmann
9
In vielen Fällen ist es nicht sinnvoll, ACID auf der Ebene eines einzelnen Dokuments zu haben, was in gewisser Weise einem einzelnen Datensatz in RDBMS entspricht. Der Transaktionsbegriff bezieht sich nicht auf eine einzelne Tabelle, und Sie können sogar einen Mechanismus für ein zweiphasiges Festschreiben verwenden und mehrere XAResource einbeziehen. Daher ist es meiner Meinung nach problematisch, auf das einzelne Dokument als ACID-konform zu verweisen, IMHO.
Yair Zaslavsky
5
Stimme Yair zu. "ACID-konform auf Dokumentebene" ist kein Verkaufsargument. Es bedeutet im Grunde nur "nicht ACID-konform". ACID sollte niemals "nur eine Zeile / ein Dokument / eine Entität" sein. Es geht darum, Ihre Daten in der gesamten Datenbank konsistent zu halten.
joshua.paling
34

Eine gute Erklärung finden Sie in "Starbucks verwendet kein Zwei-Phasen-Commit" .

Es geht nicht um NoSQL-Datenbanken, aber es zeigt den Punkt, dass Sie es sich manchmal leisten können, eine Transaktion zu verlieren oder Ihre Datenbank vorübergehend in einem inkonsistenten Zustand zu halten.

Ich würde es nicht als etwas betrachten, das "repariert" werden muss. Das Update besteht darin, eine ACID-kompatible relationale Datenbank zu verwenden. Sie wählen eine NoSQL-Alternative, wenn ihr Verhalten Ihren Anwendungsanforderungen entspricht.

Duffymo
quelle
1
Wie jede Analogie hat sie ihre Grenzen. In der Software ist es einfach, neue Array [Kassierer] zu erstellen und sie jeweils synchrone Transaktionen verarbeiten zu lassen, während die tatsächlichen Kosten dafür lächerlich teuer wären.
HRJ
16

Ich denke, andere Leute haben bereits gute Antworten gegeben. Ich möchte jedoch hinzufügen, dass es ACID NOSQL DBs gibt (wie http://ravendb.net/ ). Es ist also nicht nur eine Entscheidung NOSQL - keine ACID vs Relational mit ACID ....

SubGate
quelle
1
danke @subGate. jemand da draußen, der seine Erfahrungen mit ravenDB teilen kann und ob es tatsächlich die Anforderung erfüllt?
Nir Pengas
12

"wird nicht richtig speichern" könnte bedeuten:

  1. Standardmäßig speichert MongoDB Ihre Änderungen nicht sofort auf dem Laufwerk. Es besteht also die Möglichkeit, dass Sie einem Benutzer mitteilen, dass das Update erfolgreich ist, ein Stromausfall auftritt und das Update verloren geht. MongoDB bietet Optionen zum Steuern des Aktualisierungsgrads "Haltbarkeit". Es kann warten, bis die anderen Replikate dieses Update erhalten (im Speicher), warten, bis das Schreiben in die lokale Journaldatei erfolgt usw.

  2. Es gibt keine einfachen "atomaren" Aktualisierungen für mehrere Sammlungen und sogar mehrere Dokumente in derselben Sammlung. In den meisten Fällen ist dies kein Problem, da es mit Two Phase Commit oder einer Umstrukturierung Ihres Schemas umgangen werden kann, sodass Aktualisierungen an einem einzelnen Dokument vorgenommen werden. Siehe diese Frage: Dokumentdatenbanken: Redundante Daten, Referenzen usw. (speziell MongoDB)

Sergey
quelle
10

Ab MongoDB v4.0 sollen ACID-Transaktionen mit mehreren Dokumenten unterstützt werden. Durch die Snapshot-Isolation bieten Transaktionen eine global konsistente Ansicht der Daten und erzwingen die Alles-oder-Nichts-Ausführung, um die Datenintegrität aufrechtzuerhalten.

Sie fühlen sich wie Transaktionen aus der relationalen Welt, z.

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()

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

Grigori Melnik
quelle
Der erste Release-Kandidat von MongoDB4.0 ist out - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik
5

Bitte lesen Sie die ACID-Eigenschaften , um ein besseres Verständnis zu erhalten.

Auch in der MongoDB-Dokumentation finden Sie eine Frage und Antwort .

MongoDB ist nicht ACID-konform. Lesen Sie unten eine Diskussion über die ACID-Konformität.

  1. MongoDB ist Anur auf Dokumentebene ein Tomic. Es entspricht nicht der Definition von Atomic, die wir aus relationalen Datenbanksystemen kennen, insbesondere dem obigen Link. In diesem Sinne entspricht MongoDB nicht dem A von ACID.
  2. MongoDB ist Cstandardmäßig aktiviert. Sie können jedoch von sekundären Servern in einem Replikatsatz lesen. In diesem Fall können Sie nur eine eventuelle Konsistenz haben . Dies ist nützlich, wenn Sie leicht veraltete Daten lesen möchten.
  3. MongoDB garantiert keine ISolation (wieder gemäß obiger Definition):
  1. Bei Systemen mit mehreren gleichzeitigen Lesern und Schreibern ermöglicht MongoDB Clients, die Ergebnisse einer Schreiboperation zu lesen, bevor die Schreiboperation zurückkehrt.
  2. Wenn der Mongod vor dem Festschreiben des Journals beendet wird, haben Abfragen möglicherweise Lesedaten, die nach dem Neustart des Mongod nicht mehr vorhanden sind, selbst wenn ein Schreibvorgang erfolgreich zurückgegeben wird.

Jedoch ändert MongoDB jedes Dokument in Isolation (für Einfügungen und Aktualisierungen); Nur auf Dokumentebene, nicht bei Transaktionen mit mehreren Dokumenten.

  1. In Bezug auf die DBenutzerfreundlichkeit können Sie dieses Verhalten mit der write concernOption konfigurieren , sind sich jedoch nicht sicher. Vielleicht weiß es jemand besser.

Ich glaube, es gibt einige Forschungen, um NoSQL in Richtung ACID-Einschränkungen oder ähnlichem zu bewegen. Dies ist eine Herausforderung, da NoSQL-Datenbanken normalerweise schnell sind und ACID-Einschränkungen die Leistung erheblich beeinträchtigen können.

Ely
quelle
4

Der einzige Grund, warum Atomic die Arbeit gegen eine einzelne Sammlung ändert, besteht darin, dass die Mongodb-Entwickler kürzlich eine Datenbanksperre gegen eine sammlungsweite Schreibsperre ausgetauscht haben. Die Entscheidung, dass die erhöhte Parallelität hier den Kompromiss wert war. Mongodb ist im Kern eine Speicherzuordnungsdatei: Sie haben die Pufferpoolverwaltung an das VM-Subsystem des Computers delegiert. Da es sich immer im Speicher befindet, können sie mit sehr körnigen Sperren davonkommen: Sie führen nur speicherinterne Operationen aus, während Sie es halten, was extrem schnell sein wird. Dies unterscheidet sich erheblich von einem herkömmlichen Datenbanksystem, das manchmal gezwungen ist, E / A auszuführen, während ein Pagelock oder ein Rowlock gehalten wird.

joeshmoe
quelle
Könnten Sie bitte erklären, warum dies die Parallelität erhöht? Entschuldigung, wenn mir hier das Offensichtliche fehlt.
Batbrat
@batbrat: Betrachten Sie zwei Clients, die versuchen, gleichzeitig in verschiedene Sammlungen in derselben Datenbank zu schreiben. Bei einer Datenbanksperre muss einer der Clients warten, bis der andere fertig ist, bevor das Schreiben erfolgen kann. Mit einer Sammlungssperre können beide Clients gleichzeitig schreiben. Das ist es, was mit erhöhter Parallelität gemeint ist. Wenn beide Clients versuchen, in dieselbe Sammlung zu schreiben, muss man natürlich warten.
Jrullmann
2

"In MongoDB ist eine Operation an einem einzelnen Dokument atomar" - das ist die Sache der Vergangenheit

In der neuen Version von MongoDB 4.0 KÖNNEN Sie:

In Situationen, in denen Atomizität für Aktualisierungen mehrerer Dokumente oder Konsistenz zwischen Lesevorgängen für mehrere Dokumente erforderlich ist, bietet MongoDB die Möglichkeit, Transaktionen mit mehreren Dokumenten für Replikatsätze durchzuführen. Transaktionen mit mehreren Dokumenten können für mehrere Vorgänge, Sammlungen, Datenbanken und Dokumente verwendet werden. Transaktionen mit mehreren Dokumenten bieten ein Alles-oder-Nichts-Angebot. Wenn eine Transaktion festgeschrieben wird, werden alle in der Transaktion vorgenommenen Datenänderungen gespeichert. Wenn eine Operation in der Transaktion fehlschlägt, wird die Transaktion abgebrochen und alle in der Transaktion vorgenommenen Datenänderungen werden verworfen, ohne jemals sichtbar zu werden. Bis zum Festschreiben einer Transaktion sind außerhalb der Transaktion keine Schreibvorgänge in der Transaktion sichtbar.

Es gibt jedoch nur wenige Einschränkungen, wie und welche Vorgänge ausgeführt werden können.

Überprüfen Sie den Mongo Doc. https://docs.mongodb.com/master/core/transactions/

Mysterious25K
quelle
1

Sie können atomare Multi-Key-Updates (serialisierbare Transaktion) auf der Clientseite implementieren, wenn Ihr Speicher die Linearisierbarkeit pro Schlüssel unterstützt und diese vergleicht und festlegt (was für MongoDB gilt). Dieser Ansatz wird in Googles Percolator und in der CockroachDB verwendet, aber nichts hindert Sie daran, ihn mit MongoDB zu verwenden.

Ich habe eine schrittweise Visualisierung solcher Transaktionen erstellt. Ich hoffe, es wird Ihnen helfen, sie zu verstehen.

Wenn Sie mit der gelesenen Isolationsstufe gut umgehen können, ist es sinnvoll, sich die RAMP-Transaktionen von Peter Bailis anzusehen. Sie können auch für MongoDB auf der Client-Seite implementiert werden.

rystsov
quelle