Odesláním nové odpovědi se to vyčistí. Provedl jsem testy a znovu si přečetl zdrojový kód a jsem si jistý, že podráždění pochází z nešťastné věty v dokumentaci týkající se zápisu. S povoleným žurnálováním a j:true
zápis, zápis je odolný a neexistuje žádné záhadné okno pro ztrátu dat.
I když je žurnálování zapnuté, existuje stále šance na ztrátu zápisů v MongoDB?
Ano, protože životnost závisí také na jednotlivých operacích, na kterých se zápis týká.
"Ve výchozím nastavení je největší rozsah ztracených zápisů, tj. těch, které nebyly provedeny do deníku, ty provedené za posledních 100 milisekund."
Toto je z Manage Journaling, což znamená, že byste mohli ztratit zápisy provedené od posledního vyprázdnění žurnálu na disk.
To je správně. Žurnál je vyprázdněn samostatným vláknem asynchronně, takže můžete ztratit vše od posledního vyprázdnění.
Pokud chci delší trvanlivost, "Chcete-li přinutit mongoda, aby se zapsal do deníku častěji, můžete zadat
j:true
. Při operaci zápisu sj:true
čeká na vyřízení, mongod zkrátíjournalCommitInterval
na třetinu nastavené hodnoty."
Tohle mě taky naštvalo. Zde je to, co to znamená:
Když odešlete operaci zápisu s j:true
, nespustí vyprázdnění disku okamžitě a ne na síťovém vláknu. To dává smysl, protože by mohly existovat desítky aplikací komunikujících se stejnou instancí mongoda. Pokud by každá aplikace hodně používala žurnálování, databáze by byla velmi pomalá, protože se neustále fsynchronizuje.
Místo toho se stane, že 'vlákno trvanlivosti' převezme všechna čekající potvrzení žurnálu a vyprázdní je na disk. Vlákno je implementováno takto (moje komentáře):
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();
Takže čekající j:true
operace způsobí, že vlákno odevzdání žurnálu se odevzdá dříve než normálně, a potvrdí všechny čekající zápisy do žurnálu, včetně těch, které nemají j:true
set.
I v tomto případě to vypadá, že vyprázdnění žurnálu na disk je asynchronní, takže stále existuje možnost ztráty zápisů. Chybí mi něco o tom, jak zaručit, že se zápisy neztratí?
Zápis (nebo getLastError
příkaz) s j:true
obava o zápis do deníku bude čekat na dokončení synchronizace vlákna trvanlivosti , takže nehrozí žádné riziko ztráty dat (pokud to OS a hardware garantují).
Věta „Mezi potvrzeními žurnálu je však okno, když operace zápisu není plně trvanlivá“ pravděpodobně odkazuje na mongoda běžícího s povoleným žurnálováním, který přijímá zápis, který NE použijte j:true
napsat znepokojení. V takovém případě existuje možnost, že se zápis od posledního potvrzení deníku ztratí.
Odeslal jsem kvůli tomu hlášení o chybě dokumentů.