Blokowanie MongoDB jest inne
Blokowanie w MongoDB nie działa jak blokowanie w RDBMS, więc potrzebne jest trochę wyjaśnienia. We wcześniejszych wersjach MongoDB istniał jeden globalny zatrzask odczytu/zapisu. Począwszy od MongoDB 2.2, dla każdej bazy danych istnieje zatrzask odczytu/zapisu.
Zatrzask czytelnika-pisarza
Zatrzask jest wielokrotnym czytnikiem, jednym zapisującym i jest chciwy do zapisu. Oznacza to, że:
- W bazie danych może znajdować się nieograniczona liczba jednoczesnych czytników
- W dowolnej kolekcji w jednej bazie danych może być tylko jeden autor na raz (więcej o tym za chwilę)
- Pisarze blokują czytelników
- Przez „chciwy pisarz” rozumiem, że gdy nadejdzie żądanie zapisu, wszyscy czytelnicy są zablokowani do czasu zakończenia zapisu (więcej o tym później)
Zauważ, że nazywam to „zatrzaskiem”, a nie „zamkiem”. Dzieje się tak dlatego, że jest lekki, a w odpowiednio zaprojektowanym schemacie blokada zapisu jest utrzymywana z rzędu kilkunastu mikrosekund. Zobacz tutaj, aby uzyskać więcej informacji na temat blokowania czytników i pisarzy.
W MongoDB możesz uruchamiać tyle jednoczesnych zapytań, ile chcesz:tak długo, jak odpowiednie dane znajdują się w pamięci RAM, wszystkie będą spełnione bez konfliktów blokujących.
Aktualizacje dokumentów atomowych
Przypomnijmy, że w MongoDB poziom transakcji to jeden dokument. Wszystkie aktualizacje jednego dokumentu są Atomowe. MongoDB osiąga to, przytrzymując zatrzask zapisu tylko tak długo, jak trwa aktualizacja pojedynczego dokumentu w pamięci RAM. Jeśli jest jakaś wolno działająca operacja (w szczególności, jeśli dokument lub pozycja indeksu muszą być stronicowane z dysku), wtedy ta operacja opłaci się zatrzask zapisu. Gdy operacja zwróci zatrzask, można kontynuować następną operację w kolejce.
Oznacza to, że zapisy do wszystkich dokumentów w jednej bazie danych są serializowane. Może to stanowić problem, jeśli masz kiepski projekt schematu, a zapisy zajmują dużo czasu, ale we właściwie zaprojektowanym schemacie blokowanie nie stanowi problemu.
Pisarz-chciwy
Jeszcze kilka słów o byciu chciwym pisarzem:
Tylko jeden pisarz może jednocześnie trzymać zatrzask; wielu czytelników może jednocześnie przytrzymać zatrzask. W naiwnej implementacji pisarze mogliby głodować w nieskończoność, gdyby działał tylko jeden czytnik. Aby tego uniknąć, w implementacji MongoDB, gdy pojedynczy wątek wyśle żądanie zapisu dla określonego zatrzasku
- Wszystkie kolejne czytniki wymagające tego zatrzasku zostaną zablokowane
- Ten pisarz poczeka, aż wszyscy obecni czytelnicy skończą
- Zapisujący nabędzie zatrzask zapisu, wykona swoją pracę, a następnie zwolni zatrzask zapisu
- Wszyscy czytelnicy w kolejce będą teraz kontynuować
Rzeczywiste zachowanie jest złożone, ponieważ zachowanie chciwego pisarza współdziała z ustępowaniem w sposób, który może być nieoczywisty. Przypomnij sobie, że począwszy od wersji 2.2, istnieje oddzielny zatrzask dla każdej bazy danych, więc zapis do dowolnej kolekcji w bazie danych „A” uzyska osobny zatrzask niż zapis do dowolnej kolekcji w bazie danych „B”.
Konkretne pytania
Odnośnie konkretnych pytań:
- Blokady (właściwie zatrzaski) są utrzymywane przez jądro MongoDB tylko tak długo, jak trwa aktualizacja pojedynczego dokumentu
- Jeśli masz wiele połączeń przychodzących do MongoDB, a każde z nich wykonuje serię zapisów, zatrzask będzie utrzymywany na podstawie bazy danych tylko tak długo, jak zajmie to zakończenie zapisu
- Wiele połączeń przychodzących podczas wykonywania zapisów (aktualizacja/wstawianie/usuwanie) będzie przeplatanych
Choć brzmi to jak duży problem z wydajnością, w praktyce nie spowalnia to. Przy prawidłowo zaprojektowanym schemacie i typowym obciążeniu, MongoDB nasyci pojemność we/wy dysku — nawet w przypadku dysku SSD — zanim procent blokady dowolnej bazy danych przekroczy 50%.
Klaster MongoDB o największej pojemności, jaki znam, wykonuje obecnie 2 miliony zapisów na sekundę.