必须手动执行moveChunk的四种场景是:自动均衡器卡住、Jumbo Chunk阻塞迁移、预分片后数据分布不均、需紧急迁移热点数据;它是绕过均衡逻辑的底层操作,需通过mongos执行且参数容错率低。

什么时候必须手动执行 moveChunk
自动均衡器卡住、Jumbo Chunk 阻塞迁移、预分片后数据分布不均,或者需要紧急将热点数据迁到特定分片时,moveChunk 就是唯一能直接干预的手段。它不是“替代均衡器”,而是绕过均衡逻辑的底层操作——一旦用错参数或目标分片不可写,命令会阻塞甚至失败,且不会自动回滚。
moveChunk 命令的关键参数和常见失败原因
必须通过 mongos 执行 db.adminCommand({moveChunk: ...}),不能直连分片节点。最易出错的是 find 和 bounds 二选一没配对,或 to 指向了不存在/不可达的分片 ID。
-
find:需传入一个能命中目标 chunk 内至少一个文档的查询(如{username: "smith"}),但 MongoDB 不保证该值就是 chunk 边界点;如果该值恰好落在 chunk 外,命令报no matching chunk -
bounds:更可靠,必须严格匹配 config.chunks 中的min/max(含字段顺序、类型、边界包含性),例如{min: {a: 1, b: "x"}, max: {a: 1, b: "y"}};少一个字段或类型错(字符串 vs ObjectId)就失败 -
to:必须是shards._id字段值(查db.adminCommand({listShards: 1})),不是主机名或 replica set 名 -
forceJumbo: true:仅当目标 chunk 带jumbo: true标记且已清除标记(见下节)后才可设为true,否则会被拒绝
Jumbo Chunk 迁移前必须做的三件事
看到 sh.status(true) 提示 “has jumbo chunks” 别急着 moveChunk——带 jumbo: true 的 chunk 默认被禁止迁移,强行调用会卡死或报错 cannot move jumbo chunk。
- 先停均衡器:
sh.stopBalancer(),否则 balancer 可能并发修改元数据 - 查并确认 chunk:
use config; db.chunks.find({jumbo: true, ns: "mydb.mycoll"}),拿到它的min/max和所在shard - 清除标记:
db.runCommand({clearJumboFlags: "mydb.mycoll", min: {...}, max: {...}}),注意ns和min/max必须完全一致,否则无效
做完这三步,chunk 仍不会自动分裂,但已可被 moveChunk 正常处理。若后续还需迁移,建议同步调大 chunk size(如设为 512MB),避免迁移途中因大小超限又被标为 jumbo。
迁移后验证和清理
命令返回成功不代表数据已落地——moveChunk 是同步阻塞操作,但完成时只保证源 chunk 删除、目标 chunk 写入、config.chunks 元数据更新三者原子性达成。真正要确认,得查两处:
- 目标分片上查文档是否存在:
db.getSiblingDB("mydb").mycoll.find({...}).limit(1)(用原find条件) - config.chunks 中该 chunk 的
shard字段是否已更新,且jumbo字段消失(若曾存在) - 重启均衡器:
sh.startBalancer(),否则后续自动平衡不会触发
最容易被忽略的是:迁移过程中若发生网络中断或 mongos 挂掉,命令可能处于“半完成”状态——config 元数据已改,但目标分片没收到全部数据。此时必须人工比对源/目标分片的文档计数和校验和,不能只信命令返回值。


















