更新时间: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)。
检查孤儿文档
- 使用root或高权限账号连接到Mongos节点,将以下命令中的dbName和collName替换成待检查的数据库和集合的名称,然后执行:
db.getSiblingDB("dbName").collName.find().readPref("secondary").readConcern("local").explain("executionStats")
- 查看命令返回结果中SHARDING_FILTER阶段的chunkSkips属性,其值代表待检查集合在当前Shard节点上的孤立文档数量,当其值大于零时表示在该Shard节点上存在孤儿文档。命令返回示例如下:
- 该查询孤儿文档命令设置了查询语句的readPreference参数,会在Secondary节点上执行。
- 文档数据库服务 DDS与自建MongoDB检查孤立文档的方法一致。
- 您需要重复执行以上命令为每个集合检查孤儿文档。
- 该查询孤儿文档命令会扫描所有Shard节点上的文档遍历整个集合,当文档数据量较多时,查询耗时会比较长,并且会对数据库实例产生一定的查询压力,不建议您执行该查询命令。
- 建议您在业务低峰期直接清理孤儿文档(见下文“操作步骤”)。清理操作需要连接到集群的Shard节点。DDS集群Shard节点默认未放开连接,如您无法连接Shard节点,请开启ShardIP后再操作,或提交工单申请。
迁移影响
DRS在迁移集群时,会从Shard上抽取全量数据。正常文档和孤儿文档在不同的Shard上,DRS不会感知,都会迁移到目标库。DRS针对MongoDB迁移的冲突策略为忽略,因此最终目标库上的文档取决于哪个文档先被迁过去,会造成数据内容或行数不一致。
操作步骤
- 下载用于清除孤儿文档的cleanupOrphaned.js脚本文件。
- 修改cleanupOrphaned.js脚本文件,将test替换为待清理孤儿文档的数据库名。
- 执行以下命令,清理Shard节点下指定的数据库中所有集合的孤儿文档。
mongo --host ShardIP --port Primaryport --authenticationDatabase database -u username -p password cleanupOrphaned.js
- ShardIP:Shard节点的IP地址。
- Primaryport:Shard节点中的Primary节点的服务端口。
- database:鉴权数据库名,即数据库账号所属的数据库。
- username:登录数据库的账号。
- password:登录数据库的密码。
父主题: 实时迁移