A partir de MongoDB 8.2, las lecturas secundarias en clústeres fragmentados pueden finalizar automáticamente si existe el riesgo de que falten documentos debido a migraciones de fragmentos.
Para respaldar este nuevo comportamiento, MongoDB 8.2 introduce los siguientes cambios:
Añade
terminateSecondaryReadsOnOrphanCleanupParámetrotrue(predeterminado:)Nota
Si
terminateSecondaryReadsOnOrphanCleanupse establece enfalse, el servidor no finaliza las lecturas y podría perder documentos en colecciones fragmentadas debido a migraciones de fragmentos. Este es el comportamiento predeterminado en MongoDB 8.1 o versiones anteriores. Para obtener más información, consulte Deshabilitar la terminación de lectura secundaria.Aumenta el valor predeterminado
orphanCleanupDelaySecsde900segundos a3600segundos (1 horas)
Comportamiento
De forma predeterminada, un clúster fragmentado realiza las siguientes operaciones cuando se confirma una migración de fragmentos:
El fragmento de origen inicia un proceso de limpieza huérfano para eliminar documentos que migraron a un fragmento diferente.
El fragmento espera a que se completen todas las lecturas preexistentes en el fragmento principal.
El fragmento espera
orphanCleanupDelaySecssegundos adicionales (valor predeterminado: 1 hora).El fragmento elimina los documentos huérfanos.
Los secundarios finalizan las lecturas que comenzaron antes de que se completara la migración.
Los secundarios replican eliminaciones de documentos huérfanos.
Finalizar las lecturas secundarias antes de eliminar documentos huérfanos garantiza que las lecturas secundarias de larga duración no omitan ningún documento eliminado durante el proceso de limpieza.
Monitoring
Puede supervisar las lecturas secundarias finalizadas debido a la limpieza de huérfanos de las siguientes maneras:
Verifique el estado del servidor de su nodo secundario con el siguiente
mongoshcomando:db.serverStatus().metrics.operation.killedDueToRangeDeletionRevise sus registros
mongod. Cada terminación genera una entrada de registro como la del siguiente ejemplo:
{ "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 } }
Gestión de lecturas secundarias de larga duración
Si su aplicación realiza lecturas secundarias que superan las 1 horas en clústeres fragmentados que realizan migraciones de fragmentos, es posible que encuentre QueryPlanKilled errores (código 175 de error) debido a lecturas finalizadas.
El método recomendado para gestionar lecturas secundarias de larga duración es implementar un mecanismo de reanudación en su aplicación.
También puedes gestionar lecturas secundarias de larga duración con las siguientes estrategias alternativas:
Implementar el mecanismo de reanudación
Un mecanismo de reanudación permite a tu aplicación crear una nueva operación de lectura que comience donde terminó la operación de lectura anterior.
Para implementar un mecanismo de resumen eficaz, su aplicación debe usar un orden de clasificación consistente para los resultados de sus consultas. Tenga en cuenta los siguientes factores al seleccionar un orden de clasificación para su mecanismo de resumen:
La operación de clasificación debe utilizar un campo indexado para una ejecución eficiente de la consulta.
El campo de clasificación debe contener valores únicos.
Si los valores del campo de clasificación no son únicos, su aplicación debe implementar lógica adicional para manejar documentos que comparten el mismo valor de clasificación.
Ejemplo
Considere una base de datos cities que contiene una colección zipcodes con la siguiente estructura:
{ "state": "NY", "city": "NEW YORK", "zipcode": "00501" }
Para este ejemplo, supongamos que los valores del campo zipcode son únicos.
El siguiente código JavaScript realiza una operación de lectura secundaria para recuperar todos los documentos donde state es NY e implementa un mecanismo de reanudación para manejar errores 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 } } }
Al revisar la base de datos de ejemplo y la lógica de la aplicación, considere lo siguiente:
El código de ejemplo gestiona los errores
QueryPlanKilledcon un mecanismo de reanudación que ordena porzipcode. Ordenar por el campozipcodegarantiza un orden consistente y un valor de ordenación único para cada documento. Esto permite que la aplicación reanude la operación de lectura exactamente donde se terminó.La
cities.zipcodescolección implementa un{state: 1, zipcode: 1}índice compuesto para garantizar la eficiencia de las consultas del mecanismo de reanudación. La implementación de este índice compuesto evita tanto los escaneos de la colección como las ordenaciones en memoria, y admite operaciones de filtrado y ordenación. Para obtener más información sobre la creación de índices eficaces, consulte la Guía ESR (Igualdad, Ordenación, Rango).El error
QueryPlanKilled(código de error175) puede ocurrir por razones distintas a la finalización de lecturas secundarias. Para gestionar con precisión los erroresQueryPlanKilled, debe analizar el campoerrmsg. MongoDB devuelve el siguiente mensaje de error al finalizar una lectura secundaria:
{ code: 175, name: QueryPlanKilled, categories: [CursorInvalidatedError], errmsg: "Read has been terminated due to orphan range cleanup" }
Cuando la aplicación detecta un
QueryPlanKillederror debido a la limpieza de un rango huérfano, utiliza el último código postal procesado correctamente como punto de partida para la consulta reanudada. El operador garantiza que la aplicación no procese documentos$gtduplicados.
Pruebe sus mecanismos de reanudación en un entorno de prueba y monitoree su clúster de producción para comprender la frecuencia con la que se terminan las lecturas secundarias. Si las terminaciones ocurren con frecuencia, podría necesitar ajustar sus patrones de consulta o considerar enfoques alternativos de acceso a datos. Para saber cómo monitorizar su clúster para detectar estos errores, consulte Monitoreo.
Aumentar orphanCleanupDelaySecs
El parámetro de servidor orphanCleanupDelaySecs controla el tiempo que MongoDB espera antes de borrar un fragmento migrado de la partición de origen.
Aumentar orphanCleanupDelaySecs permite que las operaciones de lectura secundaria se ejecuten durante más tiempo. Puede configurar orphanCleanupDelaySecs tanto al inicio como en tiempo de ejecución.
El siguiente comando establece orphanCleanupDelaySecs en 2 horas:
db.adminCommand({ setParameter: 1, orphanCleanupDelaySecs: 7200 })
Importante
Aumentar orphanCleanupDelaySecs significa que los documentos huérfanos permanecen en los nodos durante más tiempo. Si aumenta este valor, ejecutar una consulta que use un índice pero no incluya la clave de fragmento podría reducir el rendimiento, ya que la consulta debe filtrar más documentos huérfanos antes de devolver resultados.
Deshabilitar la terminación de lectura secundaria
Nota
En MongoDB 8.1 o versiones anteriores, los clústeres fragmentados no finalizan automáticamente las lecturas secundarias de larga duración. Para que esto se ajuste a MongoDB 8.2 o versiones posteriores, deshabilite la finalización de lecturas secundarias.
El terminateSecondaryReadsOnOrphanCleanup parámetro de servidor controla si las lecturas secundarias de larga ejecución finalizan automáticamente antes de la eliminación del documento huérfano.
Puede desactivar la terminación de lectura secundaria configurando terminateSecondaryReadsOnOrphanCleanup en false. Puede configurar este parámetro al iniciar o ejecutar.
El siguiente comando establece terminateSecondaryReadsOnOrphanCleanup en false:
db.adminCommand({ setParameter: 1, terminateSecondaryReadsOnOrphanCleanup: false })
Advertencia
Si esta función está deshabilitada y las migraciones de fragmentos afectan la colección de destino, es posible que sus lecturas secundarias no puedan devolver todos los documentos.
Desactivar el balanceador
Puedes evitar la finalización automática de lecturas secundarias de larga duración desactivando el balanceador y no realizando ninguna migración manual.
Para deshabilitar el balanceador para colecciones específicas, utilice el configureCollectionBalancing enableBalancing campo del comando.
Para restringir las operaciones del balanceador a momentos específicos, consulte Programar la ventana de balanceo.
Advertencia
Desactivar el balanceador durante períodos prolongados puede provocar particiones desequilibradas, lo que reduce el rendimiento del clúster. Sólo desactive el balanceador si es necesario para tu caso de uso.