Co naprawdę oznaczało, że MongoDB nie jest zgodny z ACID przed wersją v4?

226

Nie jestem ekspertem od baz danych i nie mam formalnego zaplecza informatycznego, więc proszę o wyrozumiałość. Chcę poznać rodzaje negatywnych rzeczy w świecie rzeczywistym, które mogą się zdarzyć, jeśli użyjesz starej wersji MongoDB przed wersją v4 , które nie były zgodne z ACID . Dotyczy to każdej bazy danych niezgodnej z ACID.

Rozumiem, że MongoDB może wykonywać Operacje Atomowe , ale nie obsługują „tradycyjnych blokad i złożonych transakcji”, głównie ze względu na wydajność. Rozumiem również znaczenie transakcji w bazie danych i przykład, kiedy twoja baza danych jest dla banku, a aktualizujesz kilka rekordów, z których wszystkie muszą być zsynchronizowane, chcesz, aby transakcja powróciła do stanu początkowego, jeśli istnieje przerwa w zasilaniu, więc kredyt równa się zakupowi itp.

Ale kiedy wchodzę w rozmowy na temat MongoDB, ci z nas, którzy nie znają technicznych szczegółów tego, jak bazy danych są faktycznie wdrażane, zaczynają rzucać się na takie stwierdzenia:

MongoDB jest znacznie szybszy niż MySQL i Postgres, ale istnieje niewielka szansa, na przykład 1 na milion, że „nie zapisze się poprawnie”.

Ta część „nie zapisuje się poprawnie” odnosi się do tego zrozumienia: jeśli w chwili pisania w MongoDB nastąpi przerwa w dostawie prądu, istnieje szansa na określony rekord (powiedzmy, że śledzisz odsłony w dokumentach z 10 atrybutami każdego), że jeden z dokumentów zapisał tylko 5 atrybutów… co z czasem oznacza, że ​​liczniki wyświetleń strony będą „nieznacznie” wyłączone. Nigdy nie dowiesz się o ile, wiesz, że będą one w 99,999% poprawne, ale nie w 100%. Wynika to z faktu, że dopóki nie uczynisz tego konkretnie operacją atomową mongodb , nie ma gwarancji, że operacja ta będzie atomowa.

Więc moje pytanie brzmi: jaka jest prawidłowa interpretacja kiedy i dlaczego MongoDB może nie „poprawnie zapisać”? Jakie części ACID nie spełnia i pod jakimi warunkami i skąd wiesz, kiedy 0,001% twoich danych jest wyłączone? Czy nie da się tego jakoś naprawić? Jeśli nie, oznacza to, że nie powinieneś przechowywać takich rzeczy jak twój usersstół w MongoDB, ponieważ rekord może nie zostać zapisany. Ale z drugiej strony, 1/1 000 000 użytkowników może po prostu „spróbować zarejestrować się ponownie”, nie?

Właśnie szukam być może listy, kiedy / dlaczego zdarzają się negatywne rzeczy z niezgodną bazą danych ACID, taką jak MongoDB, i idealnie, jeśli istnieje standardowe obejście (na przykład uruchomienie zadania w tle w celu oczyszczenia danych lub użycie SQL tylko do tego itp.) .

Lance Pollard
źródło

Odpowiedzi:

133

Jedną rzeczą, którą tracisz z MongoDB, są transakcje z wieloma kolekcjami (tabelami). Modyfikatory atomowe w MongoDB mogą działać tylko z jednym dokumentem.

Jeśli chcesz usunąć przedmiot z ekwipunku i jednocześnie dodać go do czyjegoś zamówienia - nie możesz. Chyba że te dwie rzeczy - zapasy i zamówienia - istnieją w tym samym dokumencie (czego prawdopodobnie nie mają).

Napotkałem ten sam problem w aplikacji, nad którą pracuję, i miałem dwa możliwe rozwiązania do wyboru:

1) Ustrukturyzuj swoje dokumenty najlepiej jak potrafisz i używaj atomowych modyfikatorów najlepiej jak potrafisz, a dla pozostałego bitu użyj procesu w tle, aby wyczyścić rekordy, które mogą być niezsynchronizowane. Na przykład usuwam elementy z ekwipunku i dodam je do tablicy zarezerwowanego Inwentarza tego samego dokumentu przy użyciu modyfikatorów atomowych.

To pozwala mi zawsze wiedzieć, że przedmioty NIE są dostępne w ekwipunku (ponieważ są zarezerwowane przez klienta). Kiedy klient się wymelduje, usuwam elementy z zarezerwowanego Zapasu. Nie jest to standardowa transakcja, a ponieważ klient mógł zrezygnować z koszyka, potrzebuję trochę procesu w tle, aby przejść i znaleźć porzucone koszyki i przenieść zarezerwowane zapasy z powrotem do dostępnej puli zapasów.

Jest to oczywiście mniej niż idealne, ale jest to jedyna część dużej aplikacji, w której mongodb nie spełnia idealnie tej potrzeby. Ponadto działa do tej pory bezbłędnie. Może to nie być możliwe w wielu scenariuszach, ale ze względu na strukturę dokumentu, której używam, pasuje dobrze.

2) Użyj bazy danych transakcji w połączeniu z MongoDB. Często używa się MySQL do dostarczania transakcji na rzeczy, które są absolutnie potrzebne, pozwalając MongoDB (lub innemu NoSQL) robić to, co robi najlepiej.

Jeśli moje rozwiązanie z nr 1 nie działa na dłuższą metę, będę dalej badać połączenie MongoDB z MySQL, ale na razie nr 1 dobrze odpowiada moim potrzebom.

Bryan Migliorisi
źródło
27
Modyfikatory atomowe w MongoDB mogą działać tylko z pojedynczą kolekcją ” => Myślę, że miałeś na myśli „przeciwko jednemu dokumentowi ”.
assylias
2
Doskonała informacja, ogólnie doskonała odpowiedź, z wyjątkiem sugerowania używania MySQL.
Doug Molineux
״ Jedną rzeczą, którą tracisz z MongoDB, są transakcje z wieloma kolekcjami (tabelami). Modyfikatory atomowe w MongoDB mogą działać tylko z jednym dokumentem ״ z mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): „W MongoDB operacja zapisu jest atomowa na poziomie pojedynczego dokument, nawet jeśli operacja modyfikuje wiele osadzonych dokumentów w jednym dokumencie. ”
yoav.str
5
Nie ma już transakcji z wieloma dokumentami ACID. MongoDB ogłosił, że będą dostępne w wersji 4.0. Zobacz mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik
1
Na razie, ponieważ MongoDB 4.0 jest zgodny z ACID mongodb.com/transactions z transakcjami na wielu dokumentach. Spójrz na mongodb.com/blog/post/…
Ratah
134

W rzeczywistości nie jest poprawne, że MongoDB nie jest zgodny z ACID. Przeciwnie, MongoDB jest zgodny z ACID na poziomie dokumentu .

Każda aktualizacja jednego dokumentu to

  • Atomowa: albo całkowicie się kończy, albo nie
  • Spójny: żaden czytnik nie zobaczy aktualizacji „częściowo zastosowanej”
  • Izolowany: ponownie żaden czytelnik nie zobaczy „brudnego” odczytu
  • Trwałe: (przy odpowiedniej trosce o zapis)

MongoDB nie ma transakcji - to znaczy aktualizacji wielu dokumentów, które można wycofać i są zgodne z ACID.

Zauważ, że możesz budować transakcje na podstawie aktualizacji zgodnych z ACID do jednego dokumentu, używając zatwierdzania dwufazowego .

William Z
źródło
3
Należy pamiętać, że transakcje zatwierdzeń dwufazowych nie są zgodne z ACID. Z jakiegoś powodu wywnioskowałem coś przeciwnego, dopóki nie podążyłem za linkiem.
Justin C
1
Istnieje pytanie dotyczące trwałości rozproszonej MongoDB na poziomie dokumentu, niezależnie od konfiguracji dotyczącej zapisu. Narzędzie open source Jepsen odkryło, że dane mogą zostać utracone w obliczu partycji sieciowej, nawet jeśli problem dotyczy zapisu MAJORITY. Zobacz opis tutaj: aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann
9
Posiadanie ACID na poziomie pojedynczego dokumentu, który w pewnym sensie odpowiada jednemu rekordowi w RDBMS, nie jest przydatne w wielu przypadkach. Termin transakcji nie odnosi się do pojedynczej tabeli, a możesz nawet mieć mechanizm zatwierdzania dwufazowego i angażować kilka źródeł XAR, dlatego też odwoływanie się do pojedynczego dokumentu jako zgodnego z ACID jest nieco problematyczne, IMHO.
Yair Zaslavsky
5
Zgadzam się z Yairem. „Zgodny z ACID na poziomie dokumentu” nie jest zaletą. Zasadniczo oznacza to po prostu „niezgodny z ACID”. ACID nigdy nie miał oznaczać „tylko jednego wiersza / dokumentu / jednostki”. Chodzi o utrzymanie spójności danych w całej bazie danych.
joshua.paling
34

Dobre wyjaśnienie znajduje się w „Starbucks nie używa zatwierdzania dwufazowego” .

Nie chodzi o bazy danych NoSQL, ale ilustruje to, że czasami możesz sobie pozwolić na utratę transakcji lub tymczasową niespójność bazy danych.

Nie uważałbym tego za coś, co należy „naprawić”. Rozwiązaniem jest użycie relacyjnej bazy danych zgodnej z ACID. Wybierasz alternatywę NoSQL, gdy jej zachowanie spełnia wymagania twojej aplikacji.

duffymo
źródło
1
Jak każda analogia ma swoje ograniczenia. W oprogramowaniu łatwo jest utworzyć nową macierz [Kasjerzy] i pozwolić im przetwarzać transakcje synchroniczne, a ich rzeczywisty koszt byłby absurdalnie drogi.
HRJ,
16

Myślę, że inni ludzie już dawali dobre odpowiedzi. Jednak chciałbym dodać, że istnieją ACID NoSQL DB (jak http://ravendb.net/ ). Więc to nie tylko decyzja NOSQL - brak ACID vs. Relacyjny z ACID ....

SubGate
źródło
1
dzięki @subGate. ktoś tam, kto może podzielić się swoim doświadczeniem z ravenDB i czy rzeczywiście spełnia to wymaganie?
Nir Pengas
12

„nie zapisuje się poprawnie” może oznaczać:

  1. Domyślnie MongoDB nie zapisuje natychmiast twoich zmian na dysku. Istnieje więc możliwość, że powiesz użytkownikowi, że „aktualizacja się powiodła”, nastąpi przerwa w dostawie prądu i aktualizacja zostanie utracona. MongoDB zapewnia opcje kontroli poziomu „trwałości” aktualizacji. Może poczekać, aż inne repliki otrzymają tę aktualizację (w pamięci), poczekać na zapis do pliku dziennika lokalnego itp.

  2. Nie ma łatwych „atomowych” aktualizacji wielu kolekcji, a nawet wielu dokumentów w tej samej kolekcji. W większości przypadków nie stanowi to problemu, ponieważ można go obejść za pomocą funkcji zatwierdzania dwufazowego lub restrukturyzacji schematu, aby aktualizacje były wprowadzane w jednym dokumencie. Zobacz to pytanie: Bazy danych dokumentów: Nadmiarowe dane, referencje itp. (W szczególności MongoDB)

Siergiej
źródło
10

Począwszy od wersji MongoDB v4.0, obsługiwane będą wielodokumentowe transakcje ACID. Dzięki izolacji migawek transakcje zapewnią globalnie spójny widok danych i wymuszą wykonanie wszystkiego lub nic, aby zachować integralność danych.

Czują się jak transakcje ze świata relacyjnego, np .:

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

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

Grigori Melnik
źródło
Pierwszy kandydat do wydania MongoDB4.0 jest już dostępny - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik
5

Proszę przeczytać o właściwościach ACID, aby uzyskać lepsze zrozumienie.

Również w dokumentacji MongoDB można znaleźć pytanie i odpowiedź .

MongoDB nie jest zgodny z ACID. Przeczytaj poniżej, aby omówić zgodność z ACID.

  1. MongoDB działa Awyłącznie na poziomie dokumentu. Nie jest zgodny z definicją atomu znaną z systemów relacyjnych baz danych, w szczególności powyższym linkiem. W tym sensie MongoDB nie spełnia wymagań A z ACID.
  2. MongoDB jest Cdomyślnie jednorazowy. Można jednak czytać z serwerów pomocniczych w zestawie replik. Możesz mieć tylko ostateczną spójność tym przypadku . Jest to przydatne, jeśli nie masz nic przeciwko czytaniu nieco nieaktualnych danych.
  3. MongoDB nie gwarantuje Irozwiązania (ponownie zgodnie z powyższą definicją):
  1. W systemach z wieloma współbieżnymi czytnikami i programami rejestrującymi MongoDB pozwoli klientom odczytać wyniki operacji zapisu przed powrotem operacji zapisu.
  2. Jeśli mongod zakończy działanie przed zapisaniem dziennika, nawet jeśli zapis powróci pomyślnie, zapytania mogą mieć odczytane dane, które nie będą istnieć po ponownym uruchomieniu mongod.

Jednak MongoDB modyfikuje każdy dokument osobno (dla wstawek i aktualizacji); tylko na poziomie dokumentu, nie dotyczy transakcji obejmujących wiele dokumentów.

  1. W odniesieniu do możliwości D- możesz skonfigurować to zachowanie z write concernopcją, ale nie jestem pewien. Może ktoś wie lepiej.

Wierzę, że trwają badania nad przesunięciem NoSQL w kierunku ograniczeń ACID lub podobnych. Jest to wyzwanie, ponieważ bazy danych NoSQL są zwykle szybkie (er), a ograniczenia ACID mogą znacznie spowolnić wydajność.

Ely
źródło
4

Jedynym powodem, dla którego atomic modyfikuje pracę przeciwko pojedynczej kolekcji, jest to, że programiści mongodb niedawno wymienili blokadę bazy danych na blokadę zapisu dla całej kolekcji. Decyzja, że ​​zwiększona współbieżność tutaj była warta kompromisu. U podstaw mongodb jest plik odwzorowany w pamięci: delegowali zarządzanie pulą buforów do podsystemu VM maszyny. Ponieważ zawsze jest w pamięci, są w stanie uciec z bardzo naturalnymi szczegółami: podczas operacji będziesz wykonywać operacje tylko w pamięci, co będzie niezwykle szybkie. Różni się to znacznie od tradycyjnego systemu baz danych, który czasami jest zmuszony do wykonywania operacji we / wy podczas przytrzymywania pagelock lub rowlock.

joeshmoe
źródło
czy mógłbyś wyjaśnić, dlaczego zwiększa to współbieżność? Przepraszam, jeśli tęsknię za oczywistością tutaj.
batbrat
@batbrat: Rozważ dwóch klientów, którzy próbują jednocześnie pisać do różnych kolekcji w tej samej bazie danych. Z blokadą bazy danych jeden z klientów będzie musiał czekać na zakończenie drugiego, zanim nastąpi zapis. Z blokadą kolekcji obaj klienci mogą pisać jednocześnie. To właśnie oznacza zwiększona współbieżność. Oczywiście, jeśli obaj klienci spróbują pisać do tej samej kolekcji, trzeba będzie poczekać.
jrullmann
2

„W MongoDB operacja na jednym dokumencie ma charakter atomowy” - to już przeszłość

W nowej wersji MongoDB 4.0 MOŻESZ:

Jednak w sytuacjach, które wymagają atomowości w przypadku aktualizacji wielu dokumentów lub spójności między odczytami wielu dokumentów, MongoDB zapewnia możliwość wykonywania transakcji na wielu dokumentach przeciwko zestawom replik. Transakcje z wieloma dokumentami mogą być używane w wielu operacjach, kolekcjach, bazach danych i dokumentach. Transakcje obejmujące wiele dokumentów stanowią propozycję „wszystko albo nic”. Po zatwierdzeniu transakcji wszystkie zmiany danych dokonane w transakcji są zapisywane. Jeśli jakakolwiek operacja w transakcji zakończy się niepowodzeniem, transakcja zostanie przerwana, a wszystkie zmiany danych dokonane w transakcji zostaną odrzucone, nawet jeśli nie będą widoczne. Do czasu zatwierdzenia transakcji poza operacją nie są widoczne żadne operacje zapisu w transakcji.

Chociaż istnieje kilka ograniczeń dotyczących tego, jak i jakie operacje można wykonać.

Sprawdź dokument Mongo. https://docs.mongodb.com/master/core/transactions/

Tajemniczy 25 tys
źródło
1

Możesz wdrożyć atomowe aktualizacje z wieloma kluczami (transakcja możliwa do serializacji) po stronie klienta, jeśli pamięć obsługuje liniowość według klucza i umożliwia porównanie i zestaw (co jest prawdą w przypadku MongoDB). Takie podejście jest stosowane w Perkolatorze Google i CockroachDB, ale nic nie stoi na przeszkodzie, aby używać go z MongoDB.

Stworzyłem wizualizację takich transakcji krok po kroku . Mam nadzieję, że pomoże ci to zrozumieć.

Jeśli nie masz nic przeciwko odczytaniu zatwierdzonego poziomu izolacji, warto przyjrzeć się temu nic przeciwko odczytaniu zatwierdzonego transakcjom RAMP autorstwa Petera Bailisa. Można je również wdrożyć dla MongoDB po stronie klienta.

rystsov
źródło