千家信息网

mongodb 学习之oplog

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,背景:原来一个同事问我主从mongodb数据库为什么数据差距很大,我让他察看一下两边有啥不一样,发现主的local库有13G从却很小,进入local之后du发现有一个collection前缀的文件有1
千家信息网最后更新 2026年11月01日mongodb 学习之oplog


背景:

原来一个同事问我主从mongodb数据库为什么数据差距很大,我让他察看一下两边有啥不一样,发现

主的local库有13G从却很小,进入local之后du发现有一个collection前缀的文件有13g,说明是local数据库中一个集合太大了,推测是oplog太大了,oplog是类似于mysql的binlog oracle的archivelog

当Primary进行写操作的时候,会将这些写操作记录写入Primary的Oplog 中,而后Secondary会将Oplog 复制到本机并应用这些操作,从而实现Replication的功能。
同时由于其记录了Primary上的写操作,故还能将其用作数据恢复。
可以简单的将其视作Mysql中的binlog。

为了进一步确认,进入mongodb之后通过

show dbs

use local

show collections

看到现有的集合

然后

db.getReplicationInfo()

rs.printReplicationInfo()

了解一下复制信息以及oplog大小与使用情况

为进一步确认相应的文件是否为oplog

db.printCollectionStats()

根据展示出来的结果只需要知道两条信息:


"ns" : "local.oplog.$main",

"uri" : "statistics:table:local/collection-2-1716662444632575459"

就可以确认oplog集合的相应文件,oplog如果太大可以清理和修改大小。



MongoDB oplog是一个capped collection,创建capped collection时,createCollection可以设置size(最大字节数)和max(最大文档数)的参数,当这个集合的『总大小超过size』或者『总文档数超过max』时,在新插入文档时就会自动删除一些集合内最先插入的文档,相当于一片环形的存储空间。

oplog(local.oplog.rs集合)默认情况下配置为可用磁盘空间的5%,当oplog写满时,就会开始删除最先写入的oplog,一次正常的insert操作包含如下步骤:

  1. 将文档写入指定的集合

  2. 将写入操作记录到oplog

  3. 如果oplog满了,删除最先写入的oplog

优化策略

MongoDB 3.2为了提升写入性能,使用wiredtiger引擎时,针对local.oplog.rs这个集合的删除策略进行了优化,主要改进:

  1. 将删除动作从用户的写入路径移除,放到后台线程执行

  2. 批量删除,并不是oplog一满就立马触发删除,而是一次删除一批

实施方案

monogd启动时,会根据oplog的最大字节数将整个集合分为10-100个Stone(可以理解为oplog的一段数据,包含多个文档,Stone的具体个数oplogSizeMB的配置相关)。

WiredTigerRecordStore::OplogStones::OplogStones(OperationContext* txn, WiredTigerRecordStore* rs)    : _rs(rs) {    //...    unsigned long long maxSize = rs->cappedMaxSize();    const unsigned long long kMinStonesToKeep = 10ULL;    const unsigned long long kMaxStonesToKeep = 100ULL;    unsigned long long numStones = maxSize / BSONObjMaxInternalSize;    _numStonesToKeep = std::min(kMaxStonesToKeep, std::max(kMinStonesToKeep, numStones));    _minBytesPerStone = maxSize / _numStonesToKeep;    // ...}

其中_numStonesToKeep为oplog应该保持的Stone个数,而_minBytesPerStone代表每个Stone的最小字节数。

接下来,会根据oplog当前的大小以及_minBytesPerStone来估算下,当前的oplog大致包含的Stone数量,并通过采样的方式来获取每个Stone的起始位置(不能保证每个Stone的大小跟预期完全一样),然后将所有的Stone按顺序存储到一个队列中。

mongod在服务写请求的过程中,每次都会记录下新产生oplog的大小,当新产生的oplog的总量超过_minBytesPerStones时,就会产生一个新的Stone加入到队列中。

void WiredTigerRecordStore::OplogStones::createNewStoneIfNeeded(RecordId lastRecord) {    if (_currentBytes.load() < _minBytesPerStone) {        // Must have raced to create a new stone, someone else already triggered it.        return;    }    // ...    OplogStones::Stone stone = {_currentRecords.swap(0), _currentBytes.swap(0), lastRecord};    _stones.push_back(stone);    _pokeReclaimThreadIfNeeded(); // 唤醒后台回收oplog空间的线程}

当队列中的Stone数量超过_numStonesToKeep,后台线程就会删除最老的Stone里的数据,来回收oplog的存储空间。


修改mongodb oplog size

oplog简介:

oplog:operations log的简写,存储在一个特殊的数据库中(local),oplog就存储在其中的oplog.$main集合里面,这个集合是一个固定集合,新操作会自动替换旧的操作,以保证oplog不会超过预设的大小,其中的每个文档都代表主节点上执行的一个操作,oplog会包含所有对数据有修改的的操作(查询操作不会记录),默认下,oplog大小会占用64位的实例5%的可用磁盘空间。
mongo复制的过程:主节点应用业务操作修改到数据库中,然后记录这些操作到oplog中,从节点复制这些oplog,然后应用这些修改。ps:这些操作是异步的。如果从节点的操作已经被主节点落下很远,oplog日志在从节点还没执行完,oplog可能已经轮滚一圈了,从节点跟不上同步,复制就会停下,从节点需要重新做完整的同步,为了避免此种情况,尽量保证主节点的oplog足够大,能够存放相当长时间的操作记录。

查询oplog的大小及保存的操作记录持续的时长

repltest:PRIMARY> db.printReplicationInfo()
configured oplog size: 1024MB
log length start to end: 3705secs (1.03hrs)
oplog first event time: Thu Oct 10 2013 11:13:29 GMT+0800 (CST)
oplog last event time: Thu Oct 10 2013 12:15:14 GMT+0800 (CST)
now: Fri Oct 11 2013 16:33:42 GMT+0800 (CST)

查询从节点的数据源列表,其中有数据滞后的时间

repltest:PRIMARY> db.printSlaveReplicationInfo()
source: 192.168.1.101:37017
syncedTo: Fri Oct 11 2013 16:38:16 GMT+0800 (CST)
= 1 secs ago (0hrs)
source: 192.168.1.100:37017
no replication info, yet. State: ARBITER
so,修改oplog的大小:(下面介绍两种方式)

方式一:

The oplog exists internally as a capped collection, so you cannot modify its size in the course of normal operations.另:改变oplog大小,需要在每个节点上执行维护模式。(官方推荐)
步骤:

1:重启一个实例以单机模式,

通常再关闭server之前,使用rs.stepDown() 强制primary成为secondary

2:重新创建一个新大小,

其中包含旧的oplgo的入口条目的oplog

3:重启mongod作为replica set的成员

操作步骤:
1>: Restart a Secondary in Standalone Mode on a Different Port
关闭mongod实例:
repset:PRIMARY> use admin
repset:PRIMARY> db.shutdownServer()
重启mongod实例以单机模式,修改端口,并不要加--replSet参数
#vim /etc/mongo.conf
dbpath=/var/lib/mongodb
logpath=/var/log/mongodb/mongo.log
pidfilepath=/var/run/mongo.pid
directoryperdb=true
logappend=true
#replSet=repset
bind_ip=192.168.1.100,127.0.0.1
port=37017
oplogSize=2000
fork=true# mongod -f /etc/mongo.conf
备份oplog# mongodump --db local --collection 'oplog.rs' --port 37017
2>: Recreate the Oplog with a New Size and a Seed Entry
保存oplog的最新的时间点
> use local
> db.temp.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )
> db.temp.find()
删除旧的oplog
> db.oplog.rs.drop()
3> :Create a New Oplog
创建一个新的Oplog,大小为2G
> db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } )
插入前面保存的旧的oplog的时间点的记录
> db.oplog.rs.save( db.temp.findOne() )
> db.oplog.rs.find()
4>:Restart the Member:
关闭单机实例:
> use admin
> db.shutdownServer()
修改回配置# vim /etc/mongo.conf
dbpath=/var/lib/mongodb
logpath=/var/log/mongodb/mongo.log
pidfilepath=/var/run/mongo.pid
directoryperdb=true
logappend=true
replSet=repset
bind_ip=192.168.1.100,127.0.0.1
port=37017
oplogSize=2000
fork=true
启动mongod
# mongod -f /etc/mongo.conf
重复上述步骤到所有需要更改的节点。

方式二:

步骤:
1:停掉所有replca set节点.
2:主节点删除local库下的文件,从节点删除数据目录下所有文件.
3:修改所有节点配置文件.
4:重启所有节点.
5:重新配置replca set,从节点会重新同步所有数据(initial sync).
ps:此法好处是简单,但需要停掉服务,且如果数据量很大,初始同步的成本较高

1>:关闭mongod实例(所有节点)

> use admin
> db.shutdownServer()

2>:删除local数据库下的所有文件(PRIMARY节点)

# rm -rf /var/lib/mongodb/local/*
删除mongo数据目录(其他节点上操作,可不要删错哦,建议所有rm操作先mv,待无问题时候再删除)# rm -rf /var/lib/mongodb/*

3> 修改所有节点配置文件(oplogsize)

# vim /etc/mongo.conf
dbpath=/var/lib/mongodb
logpath=/var/log/mongodb/mongo.log
pidfilepath=/var/run/mongo.pid
directoryperdb=true
logappend=true
replSet=repset
bind_ip=192.168.1.100,127.0.0.1
port=37017
oplogSize=2000
fork=true

4> 重启所有节点mongod

> mongod -f /etc/mongo.conf



节点 数据 大小 文件 文档 实例 配置 数据库 步骤 空间 存储 方式 同步 最大 单机 后台 字节 情况 时间 最先 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 什么是科技互联网 中智农互联网科技 新华互联网科技学校 深圳互联网科技公司 奇酷互联网科技 成都互联网科技公司 狮子座互联网科技培训 镁科技互联网资讯平台 天速互联网络科技有限公司 以后互联网后是啥科技 银川新华互联网科技职业技术培训学校图片 成都铂石互联网科技做什么的 青海科技产业互联网发展 健康食品互联网创新科技园项目 上海科技产业互联网平台 江苏苏星互联网科技有限公司 工业互联网科技成果转化 陕西云淼互联网科技公司 全球科技与互联网公司市值变化 现代科技的标志之一的互联网 广州为想互联网科技有限公司 互联网和科技创新 互联网科技的发展 互联网科技ppt模板 浙南科技城互联网大厦建设工程 晋城互联网科技 美国互联网科技公司 容联科技互联网电商 长沙渺峰互联网科技有限公司 三亚科技创新互联网基地
0