优先使用replSetResizeOplog在线扩容oplog,5.0+禁止手动操作local.oplog.rs;需满足版本≥5.0、fcv=“5.0”,在Primary及各Secondary单独执行;扩容后须验证db.getReplicationInfo()中maxSizeMB和timeDiffHours是否更新,并关注applyOps积压与真实保留时长。

直接结论:优先用 replSetResizeOplog 在线扩容,别碰 local.oplog.rs 手动删集合;5.0 默认仍受 990MB 下限约束,且不支持手动写入 oplog。
查当前 oplog 实际容量和保留时长
光看配置没用,得看它现在撑得住多久。在 Primary 上执行:
db.getReplicationInfo()
重点关注两个字段:
-
maxSizeMB:当前 oplog 总大小(单位 MB) -
timeDiffHours:从最早一条日志到最新一条,跨度几小时——这才是真实“安全窗口”
如果 timeDiffHours 小于 12,尤其业务有批量导入或高峰写入,基本可以判定 oplog 正在被快速覆盖。默认 5% 磁盘空间策略在 SSD 容量大的机器上可能只给到 2–3 小时,远不够容错。
在线调整 oplog 大小(MongoDB 5.0+ 推荐路径)
5.0 完全支持 replSetResizeOplog,但必须满足三个前提:
- 所有节点版本 ≥ 5.0
-
featureCompatibilityVersion设为"5.0"(用db.adminCommand({getCmdLineOpts: 1})检查) - 命令需在 Primary 上执行,且对每个 Secondary 节点单独连上去运行(不能批量)
例如扩到 20GB:
db.adminCommand({replSetResizeOplog: 1, size: 20480})
注意:size 单位是 MB,且必须 ≥ 990(Double(20480) 在 mongosh 里更稳妥)。执行后立刻再跑 db.getReplicationInfo(),确认 maxSizeMB 和 timeDiffHours 都已更新。整个过程毫秒级写入暂停,不影响线上读写。
为什么不能直接 drop 或 truncate local.oplog.rs?
5.0 开始,MongoDB 显式禁止对 local.oplog.rs 做 drop、insert、update 等写操作——这不是权限问题,是内核级限制。试图绕过会报错:
not authorized for insert on local.oplog.rs
或者更底层的:
Cannot write to oplog directly in MongoDB 5.0+
老教程里“删集合→重启→等 initial sync”的路子,在 5.0+ 已不可行。强行停机重建 oplog 不仅风险高,还会触发全量同步,对网络和磁盘 IO 压力极大。唯一合规路径就是 replSetResizeOplog。
扩容后还要注意 apply 阶段卡顿
oplog 大了,不代表同步就快了。常见假象是:oplog 窗口够长,但 Secondary 的 applyOps 一直积压。检查方法:
db.serverStatus().metrics.repl.apply.queued
如果这个值长期 > 0,说明不是拉取慢,而是回放不过来。典型原因包括:
- Secondary 的 WiredTiger cache 设置过低(
wiredTiger.cacheSizeGB小于 4GB) - 正在后台构建大索引(
db.currentOp({secs_running: {$gt: 60}})查看长任务) - 磁盘 IOPS 不足,尤其云盘吞吐打满时,
apply阶段会严重拖慢
这时候加 oplog 毫无意义,得调 cache、拆索引、换更高性能磁盘。
真正容易被忽略的是:扩容 oplog 后,timeDiffHours 可能短暂虚高——因为新 oplog 是空的,时间跨度从第一条新日志算起。要等写入流量持续跑满几小时,才能反映真实保留能力。别刚扩完就以为万事大吉。











