Zamykání MongoDB je jiné
Zamykání v MongoDB nefunguje jako zamykání v RDBMS, takže je na místě trochu vysvětlení. V dřívějších verzích MongoDB existovala jedna globální západka pro čtení/zápis. Počínaje MongoDB 2.2 je pro každou databázi k dispozici západka pro čtení/zápis.
Zámka čtenář-zapisovatel
Západka je vícenásobná čtečka, jeden zapisovač a je nenasytná pro zápis. To znamená, že:
- V databázi může být neomezený počet simultánních čtenářů
- V každé kolekci v jedné databázi může být vždy pouze jeden autor (více o tom za chvíli)
- Autoři blokují čtenáře
- Tím "spisovatel-chtivý" mám na mysli, že jakmile přijde požadavek na zápis, všichni čtenáři jsou zablokováni, dokud zápis nedokončí (více o tom později)
Všimněte si, že tomu říkám „západka“ spíše než „zámek“. Je to proto, že je lehký a ve správně navrženém schématu je zámek zápisu držen v řádu desítek mikrosekund. Více o zamykání čtenářů a zapisovatelů naleznete zde.
V MongoDB můžete spouštět tolik současných dotazů, kolik chcete:pokud jsou příslušná data v RAM, všechny budou uspokojeny bez konfliktů zamykání.
Aktualizace atomového dokumentu
Připomeňme, že v MongoDB je úroveň transakce jeden dokument. Všechny aktualizace jednoho dokumentu jsou atomické. MongoDB toho dosahuje tak, že drží západku zápisu pouze tak dlouho, jak trvá aktualizace jednoho dokumentu v paměti RAM. Pokud existuje nějaká pomalu běžící operace (zejména pokud je třeba dokument nebo položku rejstříku nalistovat z disku), pak se tato operace vydá západka zápisu. Když operace zajistí blokování, může pokračovat další operace ve frontě.
To znamená, že zápisy do všech dokumentů v rámci jedné databáze se serializují. To může být problém, pokud máte špatný návrh schématu a vaše zápisy trvají dlouho, ale ve správně navrženém schématu není zamykání problém.
Hamtivý spisovatel
Ještě pár slov o tom, že jste spisovatel-chtivý:
Západku může současně držet pouze jeden zapisovač; západku může držet více čteček najednou. V naivní implementaci by autoři mohli donekonečna hladovět, pokud by fungovala jediná čtečka. Abyste tomu zabránili, v implementaci MongoDB, jakmile jakékoli jedno vlákno zadá požadavek na zápis pro konkrétní latch
- Všechny následující čtečky vyžadující tuto západku se zablokují
- Ten pisatel počká, dokud nebudou hotovi všichni aktuální čtenáři
- Zapisovatel získá západku zápisu, vykoná svou práci a poté západku uvolní.
- Všichni čtenáři ve frontě budou nyní pokračovat
Skutečné chování je složité, protože toto chování chtivé spisovatele interaguje s podvolováním způsoby, které nemusí být zřejmé. Připomeňme, že počínaje verzí 2.2 existuje samostatné latch pro každou databázi, takže zápisy do libovolné kolekce v databázi 'A' získají samostatný latch než zápisy do libovolné kolekce v databázi 'B'.
Konkrétní otázky
Pokud jde o konkrétní otázky:
- Zámky (ve skutečnosti zámky) jsou drženy jádrem MongoDB pouze tak dlouho, jak trvá aktualizace jednoho dokumentu
- Pokud k MongoDB přichází více připojení a každé z nich provádí sérii zápisů, bude blokování zadrženo na bázi databáze pouze tak dlouho, jak bude trvat dokončení tohoto zápisu
- Vícenásobná připojení přicházející při provádění zápisů (aktualizace/vložení/smazání) budou všechna proložena
I když to zní, jako by to byl velký problém s výkonem, v praxi to věci nezpomaluje. Díky správně navrženému schématu a typické pracovní zátěži MongoDB nasytí I/O kapacitu disku – dokonce i pro SSD – dříve, než procento uzamčení jakékoli databáze překročí 50 %.
Cluster MongoDB s nejvyšší kapacitou, o kterém vím, aktuálně provádí 2 miliony zápisů za sekundu.