文档首页/ 数据复制服务 DRS/ 常见问题/ 实时迁移/ 分片集群MongoDB迁移前清除孤儿文档
更新时间:2025-07-24 GMT+08:00

分片集群MongoDB迁移前清除孤儿文档

什么是孤儿文档

MongoDB负载均衡器(Balancer)会根据集合的分片键(Shard key)均衡数据。Balancer的工作原理是:需要Balancer的数据块(Chunk)先复制到目标Shard,成功后再删除原Shard上的Chunk,来完成一次Chunk迁移,通过多次Chunk迁移来实现均衡。在Chunk迁移时,如果发生网络闪断等不可预知的场景,完成了复制但没有完成删除,那么对同一条文档会同时存在于两个Shard上。因为Chunk迁移在MongoDB上是感知的,config会更新这条文档应该在哪个Shard上,那么另一个Shard上的文档会存在但不会被感知,后续的update、delete操作都不会作用于这个错误的Shard上的文档,那么这条文档被称为孤儿文档(Orphaned Document)。

检查孤儿文档

  1. 使用root或高权限账号连接到Mongos节点,将以下命令中的dbName和collName替换成待检查的数据库和集合的名称,然后执行:

    db.getSiblingDB("dbName").collName.find().readPref("secondary").readConcern("local").explain("executionStats")

  2. 查看命令返回结果中SHARDING_FILTER阶段的chunkSkips属性,其值代表待检查集合在当前Shard节点上的孤立文档数量,当其值大于零时表示在该Shard节点上存在孤儿文档。命令返回示例如下:

    • 该查询孤儿文档命令设置了查询语句的readPreference参数,会在Secondary节点上执行。
    • 文档数据库服务 DDS与自建MongoDB检查孤立文档的方法一致。
    • 您需要重复执行以上命令为每个集合检查孤儿文档。
    • 该查询孤儿文档命令会扫描所有Shard节点上的文档遍历整个集合,当文档数据量较多时,查询耗时会比较长,并且会对数据库实例产生一定的查询压力,不建议您执行该查询命令。
    • 建议您在业务低峰期直接清理孤儿文档(见下文“操作步骤”)。清理操作需要连接到集群的Shard节点。DDS集群Shard节点默认未放开连接,如您无法连接Shard节点,请开启ShardIP后再操作,或提交工单申请

迁移影响

DRS在迁移集群时,会从Shard上抽取全量数据。正常文档和孤儿文档在不同的Shard上,DRS不会感知,都会迁移到目标库。DRS针对MongoDB迁移的冲突策略为忽略,因此最终目标库上的文档取决于哪个文档先被迁过去,会造成数据内容或行数不一致。

操作步骤

  1. 下载用于清除孤儿文档的cleanupOrphaned.js脚本文件。
  2. 修改cleanupOrphaned.js脚本文件,将test替换为待清理孤儿文档的数据库名。
  3. 执行以下命令,清理Shard节点下指定的数据库中所有集合的孤儿文档。

    mongo --host ShardIP --port Primaryport --authenticationDatabase database -u username -p password cleanupOrphaned.js
    • ShardIP:Shard节点的IP地址。
    • Primaryport:Shard节点中的Primary节点的服务端口。
    • database:鉴权数据库名,即数据库账号所属的数据库。
    • username:登录数据库的账号。
    • password:登录数据库的密码。

    如果您有多个数据库,您需要重复执行步骤2和步骤3,分别为每个数据库的每个Shard节点清理孤立文档。