Oplog是MongoDB副本集实现主从同步的核心机制,为固定大小的capped collection,默认占磁盘5%且不低于1GB;它持续写入但覆盖不释放空间,易因配置过小或写入量大导致从节点同步延迟甚至掉线。

Oplog 是什么,为什么它会持续吃掉磁盘空间
副本集启动后,local.oplog.rs 集合会自动创建并开始记录所有写操作,这是 MongoDB 实现主从同步的核心机制。它本质是一个固定大小的 capped collection,默认占可用磁盘空间的 5%,但最小不低于 1GB(64 位系统)。一旦写入量大、主节点写频高或 oplog 空间配置过小,它就会频繁滚动覆盖——但覆盖不等于释放空间,底层文件仍保留原尺寸。
常见错误现象:db.getSiblingDB("local").oplog.rs.stats() 显示 size 很小,但 storageSize 却高达几十 GB;du -sh ./local/ 查看目录远大于实际日志数据量。
- 默认 oplog 大小不可靠:自动计算只基于磁盘总空间,不考虑业务写入节奏,生产环境务必手动调整
- 修改需重启:通过
mongod --replSet <name> --oplogSize <mb></mb></name>启动时指定,运行中无法变更 - 过小的 oplog 容易导致从节点“跟不上”:secondary 因拉取延迟被踢出同步队列,报错
cannot find a valid oplog entry
索引预分配让磁盘空间“虚胖”
MongoDB 在创建索引时不会等数据插入再逐块申请空间,而是按 WiredTiger 引擎规则预先分配连续文件段。尤其在副本集里,每个节点都要独立维护自己的索引文件,哪怕主节点已建好,secondary 同步时也会重新生成全套索引结构 —— 这意味着索引空间是 ×N 倍放大(N = 副本数)。
使用场景:新建一个含 5 个字段的复合索引,原始数据仅 200MB,但索引文件可能立刻占用 1.2GB;若副本集有 3 个节点,光这部分就多占 2.4GB(secondary 不共享主节点索引文件)。
-
db.collection.getIndexes()可查索引数量和大小,重点关注totalSize字段 - 索引名越长,BSON 存储开销越大:比如
user_profile_full_name_text_index比u_p_f_n_t_i多占约 8–12 字节/文档 - 删除无用索引后,空间不会立即回收:需执行
db.collection.dropIndex("name")+db.runCommand({compact: "collection"})(注意 compact 会阻塞写入)
副本集特有的空间冗余:local 库不止有 oplog
除了 oplog.rs,local 库还存着副本集元数据(system.replset)、临时排序/聚合中间结果(如未加 allowDiskUse: true 的大聚合)、以及部分版本升级遗留的 startup_log 和 slaves(旧版残留)。这些内容不参与复制,但每个节点都有一份完整拷贝。
容易踩的坑:直接 use local 后 db.dropDatabase() 会彻底破坏副本集,mongod 进程将拒绝启动;误删 system.replset 导致节点无法识别自身角色。
- 安全清理方式:仅对
local.startup_log可用db.startup_log.remove({})(前提是确认不是关键日志) -
local.slaves在 4.2+ 已废弃,若存在可安全db.slaves.drop() - 永远不要手动删
local目录下的任何文件,WiredTiger 不会感知,下次启动可能报WT_ERROR
为什么 db.repairDatabase() 在副本集里基本没用
db.repairDatabase() 本质是重建整个数据库文件,压缩碎片、释放已删除文档的空间。但它要求节点处于 standalone 模式(即脱离副本集),否则命令直接报错 repairDatabase is not supported on a replica set member。而脱离副本集又意味着服务中断、数据不同步风险陡增。
替代方案更现实:优先用 compact 命令针对单个集合做在线整理(支持副本集 secondary,但 primary 上执行更稳妥),或在低峰期停写、临时降级为 standalone 再 repair —— 后者仅建议用于严重空间告急且其他手段无效的极端情况。
-
compact不移动数据文件位置,不改变文件名,适合线上环境 - 执行期间集合只读,但不影响其他集合读写
- 对 WiredTiger 引擎,compact 实际触发的是 block manager 的 page 整理,效果比 repair 温和但更可控
cached,WiredTiger 缓存仍在后台持有大量脏页,df -h 和 db.stats() 的数字永远对不上。


















