Публикуване на нов отговор за изчистване на това. Направих тестове и прочетох отново изходния код и съм сигурен, че раздразнението идва от едно злополучно изречение в документацията за загриженост за писане. С активирано водене на журнал и j:true
притеснение при запис, записът е издръжлив и няма мистериозен прозорец за загуба на данни.
Дори ако журналирането е включено, все още има ли шанс да загубите записи в MongoDB?
Да, защото издръжливостта зависи и от индивидуалните операции за запис.
„По подразбиране най-голямата част от загубените записи, т.е. тези, които не са направени в дневника, са тези, направени през последните 100 милисекунди.“
Това е от Manage Journaling, което показва, че може да загубите записи, направени след последния път, когато дневникът е бил изтрит на диск.
Това е вярно. Дневникът се прочиства от отделна нишка асинхронно, така че можете да загубите всичко след последното изчистване.
Ако искам повече издръжливост, "За да принудите mongod да се ангажира по-често в дневника, можете да посочите
j:true
. При операция на запис сj:true
е в очакване, mongod ще намалиjournalCommitInterval
до една трета от зададената стойност."
Това също ме дразнеше. Ето какво означава това:
Когато изпращате операция за запис с j:true
, не задейства незабавно изчистване на диска, а не в мрежовата нишка. Това има смисъл, защото може да има десетки приложения, разговарящи с един и същ mongod екземпляр. Ако всяко приложение използваше много журналиране, db би бил много бавен, защото се синхронизира през цялото време.
Вместо това, това, което се случва, е, че „нишката за издръжливост“ ще вземе всички чакащи ангажименти в дневника и ще ги изхвърли на диск. Нишката е реализирана по следния начин (коментари ми):
sleepmillis(oneThird); //dur.cpp, line 801
for( unsigned i = 1; i <= 2; i++ ) {
// break, if any j:true write is pending
if( commitJob._notify.nWaiting() )
break;
// or the number of bytes is greater than some threshold
if( commitJob.bytes() > UncommittedBytesLimit / 2 )
break;
// otherwise, sleep another third
sleepmillis(oneThird);
}
// fsync all pending writes
durThreadGroupCommit();
Така че чакащ j:true
операцията ще накара нишката за запис на дневника да се извърши по-рано, отколкото обикновено, и ще запише всички чакащи записи в дневника, включително тези, които нямат j:true
зададено.
Дори в този случай изглежда, че изтриването на дневника на диск е асинхронно, така че все още има шанс да загубите записи. Пропускам ли нещо за това как да гарантирам, че записите няма да бъдат загубени?
Записът (или getLastError
команда) с j:true
притеснения за запис в журнал ще изчака нишката за издръжливост да завърши синхронизирането , така че няма риск от загуба на данни (доколкото ОС и хардуер гарантират това).
Изречението „Въпреки това има прозорец между записванията в журнал, когато операцията по запис не е напълно издръжлива“ вероятно се отнася до mongod, работещ с активирано журналиране, който приема запис, който НЕ използвайте j:true
пишете загриженост. В този случай има вероятност записът да се изгуби след последното записване на журнала.
Подадох доклад за грешка в документите за това.