sql >> Databáze >  >> NoSQL >> MongoDB

Zaručuje žurnálování MongoDB trvanlivost?

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 s j: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ů.



  1. MongoDB $in Query Operator

  2. Mongoose findByIdAndUpdate nevrací správný model

  3. Jaký je hlavní rozdíl mezi Redis a Membase?

  4. MongoDB $isoDayOfWeek