Starting in MongoDB 8.2, secondary reads in sharded clusters might automatically terminate if there is a risk of missing documents due to chunk migrations.从MongoDB 8.2开始,如果由于块迁移而存在丢失文档的风险,分片集群中的二次读取可能会自动终止。
To support this new behavior, MongoDB 8.2 introduces the following changes:为了支持这一新行为,MongoDB 8.2引入了以下更改:
Adds添加terminateSecondaryReadsOnOrphanCleanupparameter (default:true)terminateSecondaryReadsOnOrphanCleanup参数(默认值:true)Note
If如果terminateSecondaryReadsOnOrphanCleanupis set tofalse, the server does not terminate reads and might miss documents in sharded collections due to chunk migrations.terminateSecondaryReadsOnOrphanCleanup设置为false,则服务器不会终止读取,并且可能会由于块迁移而错过分片集合中的文档。This is the default behavior in MongoDB 8.1 or earlier. To learn more, see Disable Secondary Read Termination.这是MongoDB 8.1或更早版本中的默认行为。要了解更多信息,请参阅禁用辅助读取终止。Increases将orphanCleanupDelaySecsdefault value from900seconds to3600seconds (1 hour)orphanCleanupDelaySecs的默认值从900秒增加到3600秒(1小时)
Behavior行为
By default, a sharded cluster performs the following operations when a chunk migration commits:默认情况下,当块迁移提交时,分片集群会执行以下操作:
The source shard initiates an orphan cleanup process to delete documents that migrated to a different shard.源分片启动孤立清理过程,删除迁移到不同分片的文档。The shard waits for any pre-existing reads on the primary to complete.分片等待主分片上任何预先存在的读取完成。The shard waits an additional分片等待额外的orphanCleanupDelaySecsseconds (default: 1 hour).orphanCleanupDelaySecs秒(默认值:1小时)。The shard deletes orphaned documents.分片会删除孤立的文档。
Secondaries terminate reads that started before the migration completed.辅助人员终止在迁移完成之前开始的读取。Secondaries replicate orphaned document deletions.借调人员复制孤立文档删除。
Terminating secondary reads before deleting orphaned documents ensures that long-running secondary reads do not miss any documents deleted by the cleanup process.在删除孤立文档之前终止辅助读取可确保长时间运行的辅助读取不会错过清理过程中删除的任何文档。
Monitoring监控
You can monitor terminated secondary reads due to orphan cleanup in the following ways:您可以通过以下方式监视因孤立清理而终止的辅助读取:
Check the server status of your secondary node with the following使用以下mongoshcommand:mongosh命令检查辅助节点的服务器状态:db.serverStatus().metrics.operation.killedDueToRangeDeletionReview your查看mongodlogs. Each termination results in a log entry like the following example:mongod日志。每次终止都会产生一个日志条目,如下例所示:
{
"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
}
}Managing Long-Running Secondary Reads管理长时间运行的二次读取
If your application performs secondary reads that exceed 1 hour on sharded clusters that perform chunk migrations, you might encounter 如果应用程序在执行块迁移的分片集群上执行超过1小时的二次读取,由于读取终止,您可能会遇到QueryPlanKilled errors (error code 175) due to terminated reads.QueryPlanKilled错误(错误代码175)。
The recommended method to manage long-running secondary reads is to implement a resume mechanism in your application.管理长时间运行的二次读取的推荐方法是在应用程序中实现恢复机制。
You can also manage long-running secondary reads with the following alternative strategies:您还可以使用以下替代策略来管理长时间运行的辅助读取:
Increase增加orphanCleanupDelaySecsDisable Secondary Read Termination禁用辅助读取终止Disable the Balancer禁用平衡器
Implement Resume Mechanism实施简历机制
A resume mechanism allows your application to create a new read operation that starts where your previous read operation terminates.恢复机制允许应用程序创建一个新的读取操作,从您之前的读取操作终止的地方开始。
To implement an effective resume mechanism, your application must use a consistent sort order for your query results. Consider the following factors when selecting a sort order for your resume mechanism:为了实现有效的简历机制,应用程序必须对查询结果使用一致的排序顺序。在为简历机制选择排序顺序时,请考虑以下因素:
The sort operation should utilize an indexed field for efficient query execution.排序操作应使用索引字段以实现高效的查询执行。The sort field should contain unique values.排序字段应包含唯一值。If the sort field values are not unique, your application must implement additional logic to handle documents that share the same sort value.如果排序字段值不唯一,则应用程序必须实现其他逻辑来处理共享相同排序值的文档。
Example示例
Consider a 考虑一个包含以下结构的cities database containing a zipcodes collection with the following structure:zipcode集合的cities数据库:
{
"state": "NY",
"city": "NEW YORK",
"zipcode": "00501"
}
For this example, assume the 对于这个例子,假设zipcode field values are unique.zipcode字段值是唯一的。
The following JavaScript code performs a secondary read operation to retrieve all documents where the 以下JavaScript代码执行二次读取操作以检索state is NY and implements a resume mechanism to handle QueryPlanKilled errors:state为NY的所有文档,并实现恢复机制来处理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重新考虑非终止性错误
}
}
}
When reviewing the example database and application logic, consider the following:在查看示例数据库和应用程序逻辑时,请考虑以下几点:
The example code handles示例代码使用按QueryPlanKillederrors with a resume mechanism that sorts byzipcode.zipcode排序的恢复机制处理QueryPlanKilled错误。Sorting on the对zipcodefield ensures a consistent order and a unique sort value for each document. This allows the application to resume the read operation precisely where it was terminated.zipcode字段进行排序可确保每个文档的顺序一致,排序值唯一。这允许应用程序在终止的位置精确地恢复读取操作。Thecities.zipcodescollection implements a{state: 1, zipcode: 1}compound index to ensure the efficiency of the resume mechanism queries.cities.zipcodes集合实现了一个{state: 1, zipcode: 1}复合索引,以确保恢复机制查询的效率。Implementing this compound index prevents both collection scans and in-memory sorts, and supports filter and sort operations.实现此复合索引可以防止集合扫描和内存排序,并支持筛选和排序操作。To learn more about creating effective indexes, see The ESR (Equality, Sort, Range) Guideline.要了解有关创建有效索引的更多信息,请参阅ESR(相等、排序、范围)指南。TheQueryPlanKillederror (error code175) can occur for reasons other than terminated secondary reads.QueryPlanKilled错误(错误代码175)可能是由于终止二次读取以外的原因而发生的。To accurately handle为了准确处理QueryPlanKillederrors, you must parse theerrmsgfield. MongoDB returns the following error message when it terminates a secondary read:QueryPlanKilled错误,您必须解析errmsg字段。MongoDB在终止二次读取时返回以下错误消息:
{
code: 175,
name: QueryPlanKilled,
categories: [CursorInvalidatedError],
errmsg: "Read has been terminated due to orphan range cleanup"
}
When the application encounters a当应用程序因孤立范围清理而遇到QueryPlanKillederror due to orphan range cleanup, it uses the last successfully processed zipcode as a starting point for the resumed query.QueryPlanKilled错误时,它会使用最后一个成功处理的邮政编码作为恢复查询的起点。The$gtoperator ensures the application does not process duplicate documents.$gt运算符确保应用程序不会处理重复的文档。
Test your resume mechanisms in a test environment and monitor your production cluster to understand how often secondary reads are terminated. If terminations occur frequently, you might need to adjust your query patterns, or consider alternative data access approaches. 在测试环境中测试恢复机制,并监控生产集群,以了解二次读取终止的频率。如果频繁发生终止,您可能需要调整查询模式,或考虑其他数据访问方法。To learn how to monitor your cluster for these errors, see Monitoring.要了解如何监视集群中的这些错误,请参阅监视。
Increase 增加orphanCleanupDelaySecs
The orphanCleanupDelaySecs server parameter controls the time MongoDB waits before deleting a migrated chunk from the source shard.orphanCleanupDelaySecs服务器参数控制MongoDB在从源分片删除迁移块之前等待的时间。
Increasing 增加orphanCleanupDelaySecs allows secondary read operations to run for a longer period of time. You can set the orphanCleanupDelaySecs at both startup and runtime.orphanCleanupDelaySecs允许二次读取操作运行更长的时间。您可以在启动和运行时设置orphanCleanupDelaySecs。
The following command sets 以下命令将orphanCleanupDelaySecs to 2 hours:orphanCleanupDelaySecs设置为2小时:
db.adminCommand({
setParameter: 1,
orphanCleanupDelaySecs: 7200
})
Important
Increasing 增加orphanCleanupDelaySecs means that orphaned documents remain on nodes for a longer period of time. orphanCleanupDelaySecs意味着孤儿文档在节点上停留的时间更长。If you increase this value, executing a query that uses an index but does not include the shard key might result in degraded performance as the query must filter more orphaned documents before returning results.如果增加此值,执行使用索引但不包括分片键的查询可能会导致性能下降,因为查询在返回结果之前必须筛选更多孤立文档。
Disable Secondary Read Termination禁用辅助读取终止
Note
In MongoDB 8.1 or earlier, sharded clusters do not automatically terminate long-running secondary reads. To match this behavior in MongoDB 8.2 or later, disable secondary read termination.在MongoDB 8.1或更早版本中,分片集群不会自动终止长时间运行的辅助读取。要在MongoDB 8.2或更高版本中匹配此行为,请禁用辅助读取终止。
The terminateSecondaryReadsOnOrphanCleanup server parameter controls whether long-running secondary reads automatically terminate before orphaned document deletion.terminateSecondaryReadsOnOrphanCleanup服务器参数控制长时间运行的辅助读取是否在删除孤立文档之前自动终止。
You can disable secondary read termination by setting 您可以通过将terminateSecondaryReadsOnOrphanCleanup to false. terminateSecondaryReadsOnOrphanCleanup设置为false来禁用二次读取终止。You can set this parameter at startup or runtime.您可以在启动或运行时设置此参数。
The following command sets 以下命令将terminateSecondaryReadsOnOrphanCleanup to false:terminateSecondaryReadsOnOrphanCleanup设置为false:
db.adminCommand({
setParameter: 1,
terminateSecondaryReadsOnOrphanCleanup: false
})
Warning
If this feature is disabled and chunk migrations affect the targeted collection, your secondary reads might fail to return all documents.如果禁用此功能并且块迁移影响目标集合,则二次读取可能无法返回所有文档。
Disable the Balancer禁用平衡器
You can avoid automatically terminating long-running secondary reads by disabling the balancer and not performing any manual migrations.通过禁用平衡器并且不执行任何手动迁移,可以避免自动终止长时间运行的辅助读取。
To disable the balancer for specific collections, use the 要禁用特定集合的平衡器,请使用configureCollectionBalancing command's enableBalancing field.configureCollectionBalancing命令的enableBalancing字段。
To restrict balancer operations to specific times, see Schedule the Balancing Window.要将平衡器操作限制在特定时间,请参阅计划平衡窗口。
Warning
Disabling the balancer for extended periods of time can lead to unbalanced shards which degrade cluster performance. Only disable the balancer if it is necessary for your use case.长时间禁用平衡器可能会导致分片不平衡,从而降低集群性能。只有在用例需要时才禁用平衡器。