Postando uma nova resposta para limpar isso. Realizei testes e li o código-fonte novamente e tenho certeza que a irritação vem de uma frase infeliz na documentação do problema de gravação. Com journaling ativado e
j:true
preocupação de gravação, a gravação é durável e não há nenhuma janela misteriosa para perda de dados.
Mesmo que o journaling esteja ativado, ainda existe a chance de perder gravações no MongoDB?
Sim, porque a durabilidade também depende da preocupação de gravação das operações individuais.
"Por padrão, a maior extensão de gravações perdidas, ou seja, aquelas não feitas no diário, são aquelas feitas nos últimos 100 milissegundos."
Isso é de Gerenciar diário, que indica que você pode perder gravações feitas desde a última vez que o diário foi liberado para o disco.
Está correto. O diário é liberado por um encadeamento separado de forma assíncrona, portanto, você pode perder tudo desde a última liberação.
Se eu quiser mais durabilidade, "Para forçar o mongod a se comprometer com o diário com mais frequência, você pode especificarj:true
. Quando uma operação de gravação comj:true
está pendente, o mongod reduzirájournalCommitInterval
a um terço do valor definido."
Isso também me irritou. Aqui está o que significa:
Quando você envia uma operação de gravação com
j:true
, ele não acionará a liberação do disco imediatamente e não no thread de rede. Isso faz sentido, porque pode haver dezenas de aplicativos conversando com a mesma instância mongod. Se todos os aplicativos usassem muito o journaling, o banco de dados seria muito lento porque está sincronizando o tempo todo. Em vez disso, o que acontece é que o 'thread de durabilidade' pegará todas as confirmações de diário pendentes e as liberará para o disco. O thread é implementado assim (comentários meus):
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();
Portanto, um
j:true
pendente operação fará com que o thread de confirmação do diário seja confirmado mais cedo do que normalmente faria e confirmará todas as gravações pendentes no diário, incluindo aquelas que não têm j:true
definir.
Mesmo nesse caso, parece que a liberação do diário para o disco é assíncrona, portanto, ainda há uma chance de perder gravações. Estou faltando algo sobre como garantir que as gravações não sejam perdidas?
A escrita (ou o
getLastError
comando) com um j:true
preocupação de gravação em diário aguardará o thread de durabilidade terminar a sincronização , portanto, não há risco de perda de dados (desde que o sistema operacional e o hardware garantam isso). A frase "No entanto, há uma janela entre os commits de diário quando a operação de gravação não é totalmente durável" provavelmente se refere a um mongod em execução com o journaling ativado que aceita uma gravação que NÃO use o
j:true
escreva preocupação. Nesse caso, há uma chance de a gravação se perder desde o último commit do diário. Eu arquivei um relatório de bug docs para isso.