Заключването на MongoDB е различно
Заключването в MongoDB не работи като заключване в RDBMS, така че малко обяснение е редно. В по-ранните версии на MongoDB имаше едно глобално лостче за четене/записване. Започвайки с MongoDB 2.2, за всяка база данни има ключ за четене/записване.
Заключване на читателя-писател
Резето е с няколко четеца, с един запис и е алчно за писател. Това означава, че:
- В база данни може да има неограничен брой едновременни четци
- В дадена колекция във всяка една база данни може да има само един писател в даден момент (повече за това след малко)
- Писателите блокират читателите
- Под „жаден за писател“ имам предвид, че след като постъпи заявка за запис, всички читатели са блокирани, докато записването завърши (повече за това по-късно)
Обърнете внимание, че аз наричам това "заключване", а не "ключалка". Това е така, защото е лек и в правилно проектирана схема заключването на запис се задържа от порядъка на десетина микросекунди. Вижте тук за повече информация относно заключването на читатели-писачи.
В MongoDB можете да изпълнявате толкова едновременни заявки, колкото искате:стига съответните данни да са в RAM, всички те ще бъдат задоволени без заключващи конфликти.
Актуализации на Atomic Document
Припомнете си, че в MongoDB нивото на транзакция е един документ. Всички актуализации на един документ са атомни. MongoDB постига това чрез задържане на ключалката за запис само толкова дълго, колкото е необходимо за актуализиране на един документ в RAM. Ако има някаква бавно изпълняваща се операция (по-специално, ако документ или запис в индекс трябва да бъдат качени от диск), тогава тази операция ще подаде ключалката за запис. Когато операцията даде ключалката, тогава следващата операция на опашката може да продължи.
Това означава, че записите към всички документи в рамките на една база данни се сериализират. Това може да е проблем, ако имате лош дизайн на схемата и записите ви отнемат много време, но при правилно проектирана схема заключването не е проблем.
Писател-Алчен
Още няколко думи за алчността към писателите:
Само един писател може да държи резето наведнъж; няколко четци могат да държат ключалката наведнъж. В наивна реализация писателите биха могли да гладуват безкрайно много, ако имаше един-единствен четец. За да избегнете това, в реализацията на MongoDB, след като всяка отделна нишка направи заявка за запис за конкретно ключалка
- Всички следващи четци, които се нуждаят от това ключалка, ще блокират
- Този писател ще изчака, докато всички текущи читатели приключат
- Записващият ще придобие фиксатора за запис, ще свърши работата си и след това ще освободи фиксатора за запис
- Всички четци на опашката вече ще продължат
Действителното поведение е сложно, тъй като това алчно поведение на писателя взаимодейства с отстъпването по начини, които могат да бъдат неочевидни. Припомнете си, че започвайки с версия 2.2, има отделен ключалка за всяка база данни, така че записът към която и да е колекция в база данни „A“ ще придобие отделен ключ, отколкото записът към която и да е колекция в база данни „B“.
Конкретни въпроси
Относно конкретните въпроси:
- Заключванията (всъщност ключалките) се държат от ядрото на MongoDB само толкова дълго, колкото е необходимо за актуализиране на един документ.
- Ако имате множество връзки, влизащи в MongoDB и всяка от тях извършва серия от записвания, фиксаторът ще се задържи на базата на база данни само толкова дълго, колкото е необходимо, за да завърши това записване
- Множество връзки, идващи при извършване на запис (актуализиране/вмъкване/изтриване), всички ще бъдат преплетени
Въпреки че това звучи като голям проблем с производителността, на практика това не забавя нещата. С правилно проектирана схема и типично работно натоварване, MongoDB ще насити I/O капацитета на диска - дори за SSD - преди процентът на заключване на която и да е база данни да надхвърли 50%.
Най-големият капацитет MongoDB клъстер, за който знам, в момента извършва 2 милиона записвания в секунда.