Resharding卡住最常见原因是oplog保留窗口不足:迁移耗时超过oplog时间跨度(如2小时迁移但oplog仅保留45分钟),导致目标shard无法回放变更;需检查db.getReplicationInfo()的timeDiffHours(应≥2)、磁盘空间及FCV版本,并确认replSetResizeOplog实际生效。

Resharding 卡住,大概率不是 resharing 命令本身的问题,而是底层复制机制被阻断——最常见、最隐蔽的根源就是 oplog 保留窗口撑不住迁移节奏。
reshardCollection 执行中卡在某个 chunk 迁移不动
典型表现是 sh.status() 显示迁移进度长期停在某条 "collection": "db.coll", "chunk": "xxx",且 db.currentOp({secs_running: {$gt: 300}}) 里持续出现 resharding 相关操作。这不是网络或锁表导致的“慢”,而是同步链路断了:目标 shard 的 secondary 拉不到足够的 oplog 来回放迁移过程中的变更。
- resharding 过程中,mongos 会把 chunk 拆分、移动、更新元数据,所有这些操作都记入主节点 oplog;目标 shard 必须靠 oplog 复制来保持数据一致性
- 如果 oplog 窗口小于整个 reshading 持续时间(比如迁移耗时 2 小时,但 oplog 只保留 45 分钟),目标节点就会反复触发
RECOVERING,无法完成 initial sync 或追上主节点 - 查
db.getReplicationInfo(),重点关注timeDiffHours—— 若(尤其),基本可判定 oplog 不够用 - 别只看 primary:用
rs.printSecondaryReplicationInfo()对比所有 shard 成员的oplogSize和optimeDate,不一致就可能造成部分节点掉队
执行 replSetResizeOplog 后仍卡住,为什么没生效?
命令返回成功 ≠ oplog 已扩容,MongoDB 会静默降级或延迟应用。关键要看实际写入能力是否提升。
- 执行
db.adminCommand({replSetResizeOplog: 1, size: 20480})(20GB)后,必须立刻运行db.getReplicationInfo()确认maxSizeMB和timeDiffHours真的变了;否则说明磁盘空间不足或版本不兼容 - 检查目标 shard 所在磁盘分区剩余空间:
df -h /var/lib/mongodb—— 如果只剩 15GB,你设 20GB oplog,MongoDB 会自动回落到默认值(如 990MB),且不报错 - 确认所有 shard 节点都是 5.0+ 且
featureCompatibilityVersion≥"5.0",否则replSetResizeOplog在旧节点上会被忽略 - 扩容后观察
local.oplog.rs.stats().size是否增长,以及serverStatus.metrics.repl.buffer.count是否不再持续堆积
resharding 卡住时日志里反复出现 cannot find starting oplog entry
这句错误不是说 oplog 丢了,而是目标节点想从某个时间戳开始拉取 oplog,但那个时间戳已经不在当前 oplog 范围内——直接证明 oplog 窗口被覆盖了。
- 先查主节点最新 oplog 时间戳:
db.getSiblingDB("local").oplog.rs.find().sort({$natural: -1}).limit(1).toArray()[0].ts,转成可读时间(new Date(ts.getTime())) - 再查卡住节点的
optimeDate(来自rs.status()中该成员的lastHeartbeatMessage或optimeDate字段),两者差值若超过timeDiffHours,就是覆盖了 - 注意:resharding 期间大量 chunk 拆分和 moveChunk 操作会密集写 oplog,峰值写入量可能是日常的 3–5 倍,按日常速率估算 oplog 大小一定会低估
- 临时解法是暂停 resharing(
sh.stopResharding()),等 oplog 扩容并稳定运行 1 小时后再重试;但不要跳过 oplog 评估直接重试
真正容易被忽略的是:resharding 不是单次命令,而是一连串跨节点、跨进程的复制协同。只要任意一个 shard 的任意一个 secondary 节点 oplog 窗口不够,整个迁移就会卡在原子性边界上,且不会报明确错误。盯着 timeDiffHours 和磁盘余量,比调优 numInitialSyncAttempts 或网络超时有用得多。











