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 comofalse
, 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 de900
segundos para3600
segundos (1 hora)
Comportamento
Por padrão, um cluster fragmentado executa as seguintes operações quando uma migração de chunk é confirmada:
O fragmento de origem inicia um processo de limpeza órfão para excluir documentos que migraram para um fragmento diferente.
O fragmento aguarda a conclusão de qualquer leitura pré-existente no primário.
O shard aguarda mais
orphanCleanupDelaySecs
segundos (padrão: 1 hora).O shard exclui documentos órfãos.
Os secundários encerram as leituras iniciadas antes da conclusão da migração.
Os secundários replicam exclusões de documento órfão .
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.
Monitoramento
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 } }
Gerenciamento de leituras secundárias de longa duração
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:
Implementar mecanismo de retomada
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.
Exemplo
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 porzipcode
. A classificação no campozipcode
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 erro175
) pode ocorrer por motivos diferentes do encerramento das leituras secundárias. Para lidar com os errosQueryPlanKilled
com precisão, você deve analisar o campoerrmsg
. 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.
Aumentar orphanCleanupDelaySecs
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.
Desabilitar encerramento de leitura secundária
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.
Desabilitar o balancer
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.