MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

La journalisation MongoDB garantit-elle la durabilité ?

Publier une nouvelle réponse pour nettoyer cela. J'ai effectué des tests et relu le code source et je suis sûr que l'irritation vient d'une phrase malheureuse dans la documentation relative à l'écriture. Avec la journalisation activée et j:true problème d'écriture, l'écriture est durable et il n'y a pas de fenêtre mystérieuse pour la perte de données.

Même si la journalisation est activée, y a-t-il encore une chance de perdre des écritures dans MongoDB ?

Oui, car la durabilité dépend également de la préoccupation d'écriture des opérations individuelles.

"Par défaut, la plus grande partie des écritures perdues, c'est-à-dire celles qui ne sont pas effectuées dans le journal, sont celles effectuées au cours des 100 dernières millisecondes."

Cela provient de Gérer la journalisation, ce qui indique que vous pourriez perdre des écritures effectuées depuis la dernière fois que le journal a été vidé sur le disque.

C'est exact. Le journal est vidé par un thread séparé de manière asynchrone, vous pouvez donc tout perdre depuis le dernier vidage.

Si je veux plus de durabilité, "Pour forcer mongod à s'engager plus fréquemment dans le journal, vous pouvez spécifier j:true . Lorsqu'une opération d'écriture avec j:true est en attente, mongod réduira journalCommitInterval au tiers de la valeur définie."

Cela m'a irrité aussi. Voici ce que cela signifie :

Lorsque vous envoyez une opération d'écriture avec j:true , il ne déclenche pas le vidage du disque immédiatement, et pas sur le thread réseau. Cela a du sens, car il pourrait y avoir des dizaines d'applications parlant à la même instance mongod. Si chaque application utilisait beaucoup la journalisation, la base de données serait très lente car elle se synchronise tout le temps.

Au lieu de cela, ce qui se passe, c'est que le "thread de durabilité" prendra tous les commits de journal en attente et les videra sur le disque. Le fil est implémenté comme ceci (commentaires de moi):

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();

Donc un j:true en attente l'opération entraînera la validation du thread de validation du journal plus tôt qu'il ne le ferait normalement, et elle validera toutes les écritures en attente dans le journal, y compris celles qui n'ont pas j:true ensemble.

Même dans ce cas, il semble que le vidage du journal sur le disque soit asynchrone, il y a donc toujours une chance de perdre des écritures. Ai-je raté quelque chose sur la façon de garantir que les écritures ne sont pas perdues ?

L'écriture (ou le getLastError commande) avec un j:true le problème d'écriture journalisé attendra que le fil de durabilité termine la synchronisation , il n'y a donc aucun risque de perte de données (dans la mesure où le système d'exploitation et le matériel le garantissent).

La phrase "Cependant, il y a une fenêtre entre les validations de journal lorsque l'opération d'écriture n'est pas entièrement durable" fait probablement référence à un mongod s'exécutant avec la journalisation activée qui accepte une écriture qui ne le fait PAS utilisez le j:true écrire préoccupation. Dans ce cas, il y a un risque que l'écriture soit perdue depuis la dernière validation du journal.

J'ai déposé un rapport de bogue docs pour cela.