
# 分片集群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节点上存在孤儿文档。命令返回示例如下： 
   ![](https://support.huaweicloud.com/drs_faq/figure/zh-cn_image_0000002272782568.png "点击放大")
   ![](https://support.huaweicloud.com/drs_faq/public_sys-resources/note_3.0-zh-cn.png)
   - 该查询孤儿文档命令设置了查询语句的readPreference参数，会在Secondary节点上执行。
   
   - 文档数据库服务 DDS与自建MongoDB检查孤立文档的方法一致。
   
   - 您需要重复执行以上命令为每个集合检查孤儿文档。
    
   ![](https://support.huaweicloud.com/drs_faq/public_sys-resources/caution_3.0-zh-cn.png)
   - 该查询孤儿文档命令会扫描所有Shard节点上的文档遍历整个集合，当文档数据量较多时，查询耗时会比较长，并且会对数据库实例产生一定的查询压力，不建议您执行该查询命令。
   
   - 建议您在业务低峰期直接清理孤儿文档（见下文"操作步骤"）。清理操作需要连接到集群的Shard节点。DDS集群Shard节点默认未放开连接，如您无法连接Shard节点，请开启ShardIP后再操作，或提交[工单申请](https://console.huaweicloud.com/ticket/#/ticketindex/createIndex)。
    
   
   
 
#### 迁移影响
DRS在迁移集群时，会从Shard上抽取全量数据。正常文档和孤儿文档在不同的Shard上，DRS不会感知，都会迁移到目标库。DRS针对MongoDB迁移的冲突策略为忽略，因此最终目标库上的文档取决于哪个文档先被迁过去，会造成数据内容或行数不一致。
#### 操作步骤
1. 下载用于清除孤儿文档的[cleanupOrphaned.js](https://res-static.hc-cdn.cn/cloudbu-site/china/zh-cn/DRS/cleanupOrphaned.js)脚本文件。
2. 修改cleanupOrphaned.js脚本文件，将test替换为待清理孤儿文档的数据库名。
3. 执行以下命令，清理Shard节点下指定的数据库中所有集合的孤儿文档。
   
   ```
   mongo --host ShardIP --port Primaryport --authenticationDatabase database -u username -p password cleanupOrphaned.js
   ```
   ![](https://support.huaweicloud.com/drs_faq/public_sys-resources/note_3.0-zh-cn.png)
   - ShardIP：Shard节点的IP地址。
   
   - Primaryport：Shard节点中的Primary节点的服务端口。
   
   - database：鉴权数据库名，即数据库账号所属的数据库。
   
   - username：登录数据库的账号。
   
   - password：登录数据库的密码。
    
   ![](https://support.huaweicloud.com/drs_faq/public_sys-resources/note_3.0-zh-cn.png)
   如果您有多个数据库，您需要重复执行步骤[2]和步骤[3]，分别为每个数据库的每个Shard节点清理孤立文档。
   
   
 
