Een nieuw antwoord plaatsen om dit op te ruimen. Ik heb tests uitgevoerd en de broncode opnieuw gelezen en ik weet zeker dat de irritatie voortkomt uit een ongelukkige zin in de documentatie over schrijven. Met journaal ingeschakeld en j:true
schrijfprobleem, het schrijven is duurzaam en er is geen mysterieus venster voor gegevensverlies.
Bestaat er nog steeds een kans om schrijfacties in MongoDB te verliezen, zelfs als logboekregistratie is ingeschakeld?
Ja, omdat de duurzaamheid ook afhangt van de individuele schrijfproblemen.
"Standaard zijn de grootste verloren schrijfacties, d.w.z. schrijfacties die niet naar het journaal zijn gedaan, die in de laatste 100 milliseconden."
Dit is van Beheer journaal, wat aangeeft dat je schrijfbewerkingen kunt verliezen die zijn gemaakt sinds de laatste keer dat het journaal naar schijf is gewist.
Dat is juist. Het journaal wordt asynchroon door een aparte thread gespoeld, dus je kunt alles kwijtraken sinds de laatste flush.
Als ik meer duurzaamheid wil:"Om mongod te dwingen zich vaker aan het tijdschrift te binden, kun je j:true
specificeren . Wanneer een schrijfbewerking met j:true
is in behandeling, mongod zal journalCommitInterval
. verminderen tot een derde van de ingestelde waarde."
Dit irriteerde mij ook. Dit is wat het betekent:
Wanneer u een schrijfbewerking verzendt met j:true
, het activeert de schijfspoeling niet onmiddellijk en niet op de netwerkthread. Dat is logisch, want er kunnen tientallen applicaties zijn die met dezelfde mongod-instantie praten. Als elke toepassing veel journaling zou gebruiken, zou de db erg traag zijn omdat het de hele tijd fsynchroniseert.
In plaats daarvan, wat er gebeurt, is dat de 'duurzaamheidsthread' alle lopende journaalcommits zal nemen en ze naar de schijf zal spoelen. De thread is als volgt geïmplementeerd (commentaar van mij):
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();
Dus een wachtende j:true
operatie zal ervoor zorgen dat de journaal-commit-thread eerder wordt vastgelegd dan normaal, en het zal alle wachtende schrijfbewerkingen naar het journaal vastleggen, inclusief die welke geen j:true
hebben ingesteld.
Zelfs in dit geval lijkt het alsof het legen van het journaal naar schijf asynchroon is, dus er is nog steeds een kans om schrijfbewerkingen te verliezen. Mis ik iets over hoe te garanderen dat schrijfopdrachten niet verloren gaan?
De schrijf (of de getLastError
commando) met een j:true
gejournaliseerd schrijfprobleem zal wachten tot de duurzaamheidsthread klaar is met synchroniseren , dus er is geen risico op gegevensverlies (voor zover het besturingssysteem en de hardware dat garanderen).
De zin "Er is echter een venster tussen journaal-commits wanneer de schrijfbewerking niet volledig duurzaam is" verwijst waarschijnlijk naar een mongod die draait met journaling ingeschakeld en die een schrijfactie accepteert die NIET doet gebruik de j:true
zorg schrijven. In dat geval bestaat de kans dat het schrijven verloren gaat sinds de laatste journaaltoezegging.
Ik heb hiervoor een docs-bugrapport ingediend.