确认oplog窗口不足需在从节点执行rs.printSlaveReplicationInfo()比对syncedTo与主节点optimeDate差值,若超预估窗口(如>2小时)且db.oplog.rs.findOne({ts:{$lt:ObjectId(...)}})返回null,则证实oplog起始位置已被覆盖;此时--oplogSize无效,须清空数据目录后以新参数重启触发initial sync。

备份节点反复卡在 RECOVERING 状态,根本不是网络或磁盘权限的问题,而是它要找的 oplog 起始位置已经被主节点覆盖掉了——oplog 不是“不够用”,是“被挤没了”。
怎么确认是不是 oplog 窗口太短导致同步失败
别只看 db.getReplicationInfo() 返回的 timeDiffHours,那个只是主节点当前估算值,不反映从节点实际能否拉到起点。
- 在从节点上执行
rs.printSlaveReplicationInfo(),看syncedTo和主节点optimeDate差多少秒;如果差值持续扩大且超过你预估的 oplog 窗口(比如 > 2 小时),基本就是窗口不足 - 手动验证:从主节点
rs.status().members[0].optime.ts拿到最新ts,转成ObjectId,然后在从节点运行db.oplog.rs.findOne({ts: {$lt: ObjectId("...")}});返回null就说明该时间点之前的 oplog 已丢失 - 日志里反复出现
cannot find starting oplog entry或OplogStartMissing,基本可一锤定音
为什么改了 --oplogSize 还不管用
因为 --oplogSize 只对新启动的节点生效,对已经卡住的节点完全无效——它不会自动重试 initial sync,也不会回滚状态。
- 已处于
RECOVERING的节点,必须清空数据目录(rm -rf data/db/*),再以新--oplogSize启动,才能触发全量同步 - 4.4+ 版本默认用 WiredTiger 引擎,
oplog大小由storage.oplogMinRetentionHours控制,不是靠--oplogSize;改这个参数也需重启,且仅影响后续写入 - 直接
db.oplog.rs.drop()再create capped是高危操作,会导致副本集选举中断,绝对不要在主节点上这么做
如何安全扩容 oplog 避免二次中断
扩容不是“调大一个参数就完事”,它本质是一次有计划的数据重同步,关键在顺序和节奏。
- 先处理 Secondary:逐个下线、停 mongod、删数据目录、加
--oplogSize(建议 ≥ 24 小时写入量)、重启并加入副本集;用mongostat -o 1000观察oplog增速来估算大小 - Primary 必须最后处理:先
rs.stepDown()降级,等新主节点稳定后再对其执行同样流程 - MongoDB 4.0+ 可用
db.adminCommand({replSetResizeOpLog: 1, size: 2000})在线调整,但注意:该命令只对当前节点生效,且不能缩小,只支持增大 - 扩容后务必验证:
db.getReplicationInfo()中timeDiffHours应明显上升,且从节点rs.status()中optimeDate能稳定追平
最常被忽略的一点:监控不能只盯 timeDiffHours,得同时看“窗口收缩速度”和“同步追赶速度”的差值——哪怕显示还有 5 小时,如果从节点每分钟落后 10 秒,而 oplog 每小时被覆盖 30 分钟,那它撑不过 3 小时就会再次掉队。


















