Menu Docs
Página inicial do Docs
/
Manual do banco de dados
/

Leituras secundárias de longa duração em clusters fragmentados

A partir do MongoDB 8.2, as leituras secundárias em clusters fragmentados podem ser encerradas automaticamente se houver o risco de documentos ausentes devido a migrações de chunks.

Para suportar este novo comportamento, o MongoDB 8.2 introduz as seguintes alterações:

  • Adiciona o parâmetro terminateSecondaryReadsOnOrphanCleanup (padrão: true)

    Observação

    Se terminateSecondaryReadsOnOrphanCleanup estiver definido como false, o servidor não encerrará as leituras e poderá perder documentos em coleções fragmentadas devido a migrações de blocos. Este é o comportamento padrão no MongoDB 8.1 ou anterior. Para saber mais, consulte Desativar a Terminação de Leitura Secundária.

  • Aumenta orphanCleanupDelaySecs valor padrão de 900 segundos para 3600 segundos (1 hora)

Por padrão, um cluster fragmentado executa as seguintes operações quando uma migração de chunk é confirmada:

  1. O fragmento de origem inicia um processo de limpeza órfão para excluir documentos que migraram para um fragmento diferente.

    1. O fragmento aguarda a conclusão de qualquer leitura pré-existente no primário.

    2. O shard aguarda mais orphanCleanupDelaySecs segundos (padrão: 1 hora).

    3. O shard exclui documentos órfãos.

  2. Os secundários encerram as leituras iniciadas antes da conclusão da migração.

  3. Os secundários replicam exclusões de documento órfão .

Diagrama mostrando o ciclo de vida de uma leitura secundária de longa duração que é encerrada devido a uma migração de partes.

Encerrar leituras secundárias antes de excluir documentos órfãos garante que leituras secundárias de longa duração não perderão nenhum documento excluído pelo processo de limpeza.

Você pode monitorar leituras secundárias encerradas devido à limpeza órfã das seguintes maneiras:

  • Verifique o status do servidor do seu nó secundário com o seguinte comando mongosh:

    db.serverStatus().metrics.operation.killedDueToRangeDeletion

  • Revise seus registros do mongod. Cada encerramento resulta em uma entrada de registro como o exemplo a seguir:

{
"t": {
"$date": "2025-06-11T12:11:43.361+02:00"
},
"s": "I",
"c": "SHARDING",
"id": 10016300,
"svc": "S",
"ctx": "conn93",
"msg": "Read has been terminated due to orphan range cleanup",
"attr": {
"type": "command",
...
"workingMillis": 0,
"durationMillis": 0,
"orphanCleanupDelaySecs": 3600
}
}

Se o seu aplicação realizar leituras secundárias que excedam 1 horas em clusters fragmentados que executam migrações de chunks, você poderá encontrar QueryPlanKilled erros (código de erro 175) devido ao encerramento das leituras.

O método recomendado para gerenciar leituras secundárias de longa duração é implementar um mecanismo de retomada em seu aplicação.

Você também pode gerenciar leituras secundárias de longa duração com as seguintes estratégias alternativas:

Um mecanismo de retomada permite que seu aplicação crie uma nova operação de leitura que começa onde termina sua operação de leitura anterior.

Para implementar um mecanismo de retomada eficaz, seu aplicação deve usar uma ordem de classificação consistente para os resultados da consulta. Considere os seguintes fatores ao selecionar uma ordem de classificação para seu mecanismo de retomada:

  • A operação de classificação deve utilizar um campo indexado para execução eficiente da query.

  • O campo de classificação deve conter valores únicos.

    • Se os valores do campo de classificação não forem exclusivos, seu aplicação deverá implementar lógica adicional para lidar com documentos que compartilham o mesmo valor de classificação.

Considere um banco de dados cities contendo uma collection zipcodes com a seguinte estrutura:

{
"state": "NY",
"city": "NEW YORK",
"zipcode": "00501"
}

Para este exemplo, suponha que os valores de campo zipcode sejam únicos.

O seguinte código JavaScript executa uma operação de leitura secundária para recuperar todos os documentos onde o state é NY e implementa um mecanismo de retomada para lidar com erros QueryPlanKilled:

let readDoc;
let latestZip;
let cursor = db.getSiblingDB("cities").zipcodes.find({
state: "NY"
})
.sort({zipcode: 1})
.readPref("secondary");
while(cursor.hasNext()) {
try {
readDoc = cursor.next();
// process `readDoc` here
latestZip = readDoc.zipcode;
} catch (err) {
if (err.code === 175 &&
err.errmsg.includes("Read has been terminated due to orphan range cleanup")) {
console.log("Query terminated, resuming from zipcode:", latestZip);
cursor = db.getSiblingDB("cities").zipcodes.find({
state: "NY",
zipcode: {$gt: latestZip}
})
.sort({zipcode: 1})
.readPref("secondary");
} else {
throw err; // Rethrow non-termination errors
}
}
}

Ao revisar o banco de dados de exemplo e a lógica do aplicação , considere o seguinte:

  • O código de exemplo lida com erros QueryPlanKilled com um mecanismo de retomada que classifica por zipcode. A classificação no campo zipcode garante uma ordem consistente e um valor de classificação exclusivo para cada documento. Isso permite que o aplicação retome a operação de leitura precisamente onde foi encerrado.

  • A collection cities.zipcodes implementa um índice composto {state: 1, zipcode: 1} para garantir a eficiência das queries do mecanismo de retomada. A implementação desse índice composto evita varreduras de collections e classificações na memória, e oferece suporte a operações de filtro e classificação. Para saber mais sobre como criar índices eficazes, consulte a diretriz ESR (Equality, Sort, Range).

  • O erro QueryPlanKilled (código de erro 175) pode ocorrer por motivos diferentes do encerramento das leituras secundárias. Para lidar com os erros QueryPlanKilled com precisão, você deve analisar o campo errmsg. O MongoDB retorna a seguinte mensagem de erro quando encerra uma leitura secundária:

{
code: 175,
name: QueryPlanKilled,
categories: [CursorInvalidatedError],
errmsg: "Read has been terminated due to orphan range cleanup"
}
  • Quando o aplicação encontra um erro QueryPlanKilled devido à limpeza do intervalo órfão, ele usa o último código postal processado com sucesso como ponto de partida para a query retomada. O operador $gt garante que o aplicação não processe documentos duplicados.

Teste seus mecanismos de retomada em um ambiente de teste e monitore seu cluster de produção para entender com que frequência as leituras secundárias são encerradas. Se os encerramentos ocorrerem com frequência, talvez seja necessário ajustar seus padrões de query ou considerar abordagens alternativas de acesso a dados. Para saber como monitorar seu cluster em busca desses erros, consulte Monitoramento.

O parâmetro de servidor orphanCleanupDelaySecs controla o tempo que o MongoDB espera antes de excluir um chunk migrado do shard de origem.

O aumento do orphanCleanupDelaySecs permite que as operações de leitura secundária sejam executadas por um longo período de tempo. Você pode definir o orphanCleanupDelaySecs na inicialização e no tempo de execução.

O seguinte comando define orphanCleanupDelaySecs para 2 horas:

db.adminCommand({
setParameter: 1,
orphanCleanupDelaySecs: 7200
})

Importante

Aumentar orphanCleanupDelaySecs significa que os documentos órfãos permanecem nos nós por um longo período de tempo. Se você aumentar esse valor, a execução de uma query que use um índice, mas que não inclua a chave de shard, poderá resultar em desempenho degradado, pois a query deve filtrar mais documentos órfãos antes de retornar resultados.

Observação

No MongoDB 8.1 ou anterior, os clusters fragmentados não encerram automaticamente leituras secundárias de longa duração. Para corresponder a esse comportamento no MongoDB 8.2 ou posterior, desative o encerramento de leitura secundário.

O parâmetro de servidor terminateSecondaryReadsOnOrphanCleanup controla se as leituras secundárias de longa duração terminam automaticamente antes da exclusão do documento órfão.

Você pode desabilitar a terminação secundária de leitura configurando terminateSecondaryReadsOnOrphanCleanup para false. Você pode definir este parâmetro na inicialização ou em tempo de execução.

O seguinte comando define terminateSecondaryReadsOnOrphanCleanup para false:

db.adminCommand({
setParameter: 1,
terminateSecondaryReadsOnOrphanCleanup: false
})

Aviso

Se esse recurso estiver desabilitado e as migrações de chunks afetarem a collection direcionada, suas leituras secundárias poderão não retornar todos os documentos.

Você pode evitar o encerramento automático de leituras secundárias de longa duração desativando o balanceador e não realizando migrações manuais.

Para desabilitar o balanceador para coleções específicas, use o comando configureCollectionBalancing do campo enableBalancing.

Para restringir as operações do balanceador a horários específicos, consulte Agendar a janela de balanceamento.

Aviso

Desabilitar o balanceador por longos períodos de tempo pode levar a shards desequilibrados que degradam o desempenho do cluster. Desative o balanceador somente se for necessário para o seu caso de uso.

Voltar

A fusão automática

Nesta página