MongoDB 4.4+ 支持在线扩容 oplog(replSetResizeOplog),4.2 及更早版本需滚动重建;确认 oplog 不足需验证从节点能否定位旧 ts,而非仅看 timeDiffHours;扩容后仍同步慢应优先排查 applyOps 回放瓶颈。

MongoDB 4.4+ 可在线执行 replSetResizeOplog 命令扩容,无需停机、无需 initial sync;4.2 及更早版本不支持热修改,必须滚动重建 oplog,风险高、耗时长。
怎么确认 Oplog 空间真的不够了
别只看 db.getReplicationInfo() 返回的 timeDiffHours 数值——它只是主节点视角的估算。真正要命的是从节点拉取时是否还能定位到起点。
- 在从节点执行
db.oplog.rs.findOne({ts: {$lt: ObjectId("...")}}),其中ObjectId来自主节点rs.status().members[0].optime.ts;返回null就说明已丢失该时间点前的 oplog - Secondary 日志里反复出现
Need to reclone collection due to oplog gap或OplogStartMissing,基本可锁定是 oplog 覆盖导致 -
rs.printSlaveReplicationInfo()显示 lag 持续增长,且timeDiffHours (比如 lag 最高到 3600 秒 = 1 小时,但 oplog 窗口只剩 0.8 小时),窗口收缩速度已超过追赶速度
4.4+ 版本如何在线扩容 Oplog
前提是所有节点都已升级到 4.4+,且 featureCompatibilityVersion 已设为 "4.4"(通过 db.adminCommand({setFeatureCompatibilityVersion: "4.4"}) 设置)。
- 在 Primary 上执行:
db.adminCommand({replSetResizeOplog: 1, size: 10240}),单位是 MB(例如扩到 10GB) - 命令会自动后台重建 oplog:先创建新 capped 集合 → 复制旧内容 → 切换指针 → 删除旧集合;全程读写不受影响,仅写入有毫秒级短暂阻塞
- 执行后立刻验证:
db.getReplicationInfo()中maxSizeMB应更新,timeDiffHours显著增加;再用上面的findOne方法在 Secondary 上确认旧 ts 是否可读 - 注意:不能对正在 initial sync 的节点执行该命令;若某节点状态异常(如
STARTUP2卡死),先解决其同步问题再扩容
4.2 及更早版本只能滚动重建
没有“在线”选项,所谓“热操作”是伪命题。强行清空 local.oplog.rs 或用 captrunc 会破坏 capped 属性,导致节点无法启动或同步中断。
- 标准做法是:逐个下线 Secondary → 停 mongod → 删除其
data/db/local.oplog.rs对应的.wt文件(不是删集合!)→ 修改启动参数加--oplogSize 10240→ 启动,触发 initial sync - Primary 必须最后处理,且需确保在它重建期间,至少有一个 Secondary 在线提供服务;否则会丧失写能力
- 重建期间,该节点完全离线,initial sync 耗时取决于数据量和网络带宽;若原 oplog 就太小,新节点可能再次卡在
STARTUP2,需同步调大主节点 oplog(先扩 Primary,再扩 Secondary) - 切勿使用
mongodump/mongorestore替代 initial sync——它不包含 oplog 位点,无法衔接复制链
扩容后仍同步慢?重点检查 applyOps 阶段
Oplog 拉取本身是单线程 per-sync-source,加配置项(如 numInitialSyncAttempts)对日常延迟毫无作用。瓶颈往往不在拉取,而在回放。
- 查日志是否有大量
build index、update large document或WiredTiger cache overflow相关记录 - 观察
mongostat -o 1000中netIn和netOut是否远高于qr/qw,说明拉取快但应用慢 - 临时禁用从节点上的慢查询或聚合任务;检查 WiredTiger cache 大小是否足够(
db.serverStatus().wiredTiger.cache中bytes currently in the cache接近上限时需调大wiredTigerCacheSizeGB) - 索引构建卡住时,可手动清理
data/db/_tmp/和未完成的index-*.wt文件(需先停 mongod),再重启
最常被忽略的一点:扩容 oplog 只是延长了容错窗口,不能提升同步吞吐。如果从节点 applyOps 长期跟不上,哪怕给 100GB oplog,迟早还会掉出窗口——得先解决回放瓶颈,再谈大小。











