Sender et nyt svar for at rydde op i dette. Jeg udførte test og læste kildekoden igen, og jeg er sikker på, at irritationen kommer fra en uheldig sætning i skrivebekymringsdokumentationen. Med journalføring aktiveret og j:true
skrive bekymring, skrivningen er holdbar, og der er intet mystisk vindue for datatab.
Selvom journalføring er aktiveret, er der så stadig en chance for at miste skriverier i MongoDB?
Ja, for holdbarheden afhænger også af de enkelte operationer skriv bekymring.
"Som standard er det største omfang af tabte skrivninger, dvs. dem, der ikke er foretaget til journalen, dem, der er foretaget inden for de sidste 100 millisekunder."
Dette er fra Manage Journaling, som indikerer, at du kan miste skrivninger, der er foretaget siden sidste gang, journalen blev tømt til disken.
Det er korrekt. Journalen skylles asynkront af en separat tråd, så du kan miste alt siden sidste flush.
Hvis jeg vil have mere holdbarhed, "For at tvinge mongod til at forpligte sig til tidsskriftet oftere, kan du angive j:true
. Når en skriveoperation med j:true
afventer, vil mongod reducere journalCommitInterval
til en tredjedel af den indstillede værdi."
Det irriterede mig også. Her er, hvad det betyder:
Når du sender en skriveoperation med j:true
, udløser det ikke diskskylningen med det samme, og ikke på netværkstråden. Det giver mening, fordi der kan være snesevis af applikationer, der taler til den samme mongod-instans. Hvis alle programmer skulle bruge journalføring meget, ville db være meget langsom, fordi den fsynkroniserer hele tiden.
Det, der i stedet sker, er, at 'holdbarhedstråden' vil tage alle afventende journalforpligtelser og skylle dem til disken. Tråden er implementeret sådan her (kommentarer mine):
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();
Så en afventende j:true
operation vil få journal-commit-tråden til at commit tidligere, end den normalt ville, og den vil commite alle afventende skrivninger til journalen, inklusive dem, der ikke har j:true
sæt.
Selv i dette tilfælde ser det ud til, at det er asynkront at skylle journalen til disken, så der er stadig en chance for at miste skrivninger. Mangler jeg noget om, hvordan man garanterer, at skrivninger ikke går tabt?
Skrivningen (eller getLastError
kommando) med en j:true
journaliseret skrive bekymring vil vente på, at holdbarhedstråden afslutter synkroniseringen , så der er ingen risiko for tab af data (så vidt OS og hardware garanterer det).
Sætningen "Der er dog et vindue mellem journalforpligtelser, når skriveoperationen ikke er fuldt holdbar" henviser sandsynligvis til en mongod, der kører med journalføring aktiveret, og som accepterer en skrivning, der IKKE gør. brug j:true
skrive bekymring. I så fald er der en chance for, at skrivningen forsvinder siden sidste journalindføring.
Jeg indsendte en docs fejlrapport for dette.