副本集故障转移期间的回滚
当成员在故障转移后重新加入其副本集时,回滚会恢复前主节点的写操作。只有主节点在降级之前接受了辅助节点尚未成功复制的写操作时,才需要回滚。当主节点作为辅助节点重新加入数据集时,会恢复或“回滚”其写操作,以保持数据库与其他成员的一致性。
MongoDB 试图避免回滚,这种情况应该很少发生。当发生回滚时,往往是网络分区造成的。如果辅助节点无法跟上前主节点操作吞吐量,就会增加回滚的大小和影响。
如果写操作在主节点降级之前复制到副本集的另一个成员,并且该成员对副本集的大多数成员仍然可用和可访问,则不会发生回滚。
收集回滚数据
配置回滚数据
createRollbackDataFiles
参数可控制是否在回滚期间创建回滚文件。
Rollback Data
默认情况下,当发生回滚时,MongoDB 会将回滚数据写入 BSON 文件。
对于数据发生了回滚的每个集合,回滚文件位于 <dbpath>/rollback/<collectionUUID>
目录中,文件名的格式如下:
removed.<timestamp>.bson
例如,如果 reporting
数据库中的集合 comments
的数据发生回滚:
<dbpath>/rollback/20f74796-d5ea-42f5-8c95-f79b39bad190/removed.2020-02-19T04-57-11.0.bson
其中的 <dbpath>
是 mongod
的dbPath
。
提示
集合名称
要获取集合名称,可以在 MongoDB 日志中搜索 rollback file
。例如,如果日志文件为 /var/log/mongodb/mongod.log
,可以使用 grep
在日志中搜索 "rollback file"
的实例:
grep "rollback file" /var/log/mongodb/mongod.log
或者,你可以循环浏览所有数据库,为特定的 UUID 运行 db.getCollectionInfos()
,直到找到匹配项为止。例如:
var mydatabases=db.adminCommand("listDatabases").databases; var foundcollection=false; for (var i = 0; i < mydatabases.length; i++) { let mdb = db.getSiblingDB(mydatabases[i].name); collections = mdb.getCollectionInfos( { "info.uuid": UUID("20f74796-d5ea-42f5-8c95-f79b39bad190") } ); for (var j = 0; j < collections.length; j++) { // Array of 1 element foundcollection=true; print(mydatabases[i].name + '.' + collections[j].name); break; } if (foundcollection) { break; } }
回滚数据排除
如果要回滚的操作是删除集合或文档,则删除集合或文档的回滚不会写入回滚数据目录。
警告
如果写入操作使用了 { w: 1 }
写关注,那么在写入操作完成前主节点重启的情况下,回滚目录可能会排除 oplog hole 之后提交的写操作。
读取回滚数据
要读取回滚文件的内容,请使用 bsondump
。根据应用程序的内容和知识,管理员可以决定下一步要采取的行动。
避免副本集回滚
对于副本集,写关注 { w: 1 }
只提供对主节点上写操作的确认。如果主节点在写入操作复制到任意从节点之前退出,则可能会回滚数据。其中包括在使用 { w: 1 }
写关注提交的多文档事务中写入的数据。
日记和写关注 majority
为了防止回滚已向客户端确认的数据,请在启用日志记录功能的情况下运行所有有投票权节点,并使用{ w: "majority" } 写关注来保证写入操作在返回之前传播到大多数副本集节点并向发行客户端确认。
从 MongoDB 5.0 开始,{ w: "majority" }
是多数 MongoDB 部署的默认写关注。请参阅隐式默认写关注。
将 writeConcernMajorityJournalDefault
设置为 false
时,MongoDB 不会等待 w: "majority"
写入在写入到磁盘日志后才确认写入。例如,"majority"
写操作可能会在给定副本集中的大部分节点发生临时断连(例如崩溃和重启)的情况下回滚。
可回滚数据的可见性
无论写入操作的写关注级别如何,使用
"local"
或"available"
读关注(read concern)的其他客户端均可在写入操作被发起它的客户端确认之前,看到该操作的结果。使用
"local"
或"available"
读关注的客户端可读取数据,而这些数据后续可能会在副本集故障转移期间进行回滚。
对于多文档事务中的操作,当事务提交时,该事务中进行的所有数据更改都将保存并在事务外部可见。换言之,一个事务不会在回滚其他事务的同时提交某些更改。
在事务进行提交前,在事务中所做的数据更改在事务外不可见。
不过,当事务写入多个分片时,并非所有外部读取操作都需等待已提交事务的结果在各个分片上可见。例如,如果事务已提交并且写入 1 在分片 A 上可见,但写入 2 在分片 B 上尚不可见,则读关注 "local"
处的外部读取可以在不看到写入 2 的情况下读取写入 1 的结果。
回滚考虑因素
用户操作
从 4.2 版开始,当成员进入 ROLLBACK
状态时,MongoDB 会终止所有正在进行的用户操作。
索引构建
对于功能兼容版本 (fcv)
"4.2"
,MongoDB 会等待任何正在进行的索引构建完成后再开始回滚。
有关索引构建过程的更多信息,请参阅在填充集合上构建索引。
"majority"
读关注被禁用时的索引操作
禁用 "majority"
读关注可防止修改索引的 collMod
命令回滚。如果需要回滚此类操作,则必须将受影响的节点与主节点重新同步。
大小限制
MongoDB 支持以下回滚算法,它们具有不同的大小限制:
恢复到时间戳,其中以前的主节点恢复到一致的时间点并应用操作,直到它赶上同步源的历史分支。这是默认回滚算法。
在使用该算法时,MongoDB 不限制您可以回滚的数据量。
通过重新获取回滚,其中以前的主节点找到其 oplog 和同步源的 oplog 之间的共同点。然后,该节点检查并恢复其 oplog 中的所有操作,直至到达该共同点。只有在配置文件中的
enableMajorityReadConcern
设置设为false
时,才会通过重新获取回滚。在使用该算法时,MongoDB 最多只能回滚 300 MB 数据。
注意
从 MongoDB 5.0 开始,
enableMajorityReadConcern
设置为true
,并且无法进行更改。
回滚运行时间限制
回滚时限默认为 24 小时,可使用 rollbackTimeLimitSecs
参数配置。
MongoDB 将经过的时间测量为 oplog 中第一个共通操作与正在回滚的节点的 oplog 中最后一个条目之间的时间。