副本集故障转移期间的回滚
回滚会将某个从前的主节点在成员重新加入其 副本集 后的 故障转移 期间执行的写操作撤销。只有在主节点已经接受了一些从 次要节点 处未能成功复制的写操作时,回滚才是必要的。当主节点作为次要节点重新加入集合时,它会撤销,或“回滚”其写操作,以保持与其他成员的数据库一致性。
MongoDB 试图避免回滚,这应该很少发生。当回滚确实发生时,通常是由于网络分区造成的。次要节点如果跟不上前主节点上的操作吞吐量,会增加回滚的大小和影响。
如果写操作在主节点降级之前已复制到副本集的另一个成员,并且该成员仍然可供副本集的大多数成员访问,则不会发生回滚。
收集回滚数据
配置回滚数据
参数 createRollbackDataFiles
控制在回滚过程中是否创建回滚文件。
回滚数据
默认情况下,当发生回滚时,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
提示
集合名称
要获取集合名称,您可以在MongoDB日志中搜索回滚文件
。例如,如果日志文件是/var/log/mongodb/mongod.log
,则可以使用grep
在日志中搜索"rollback file"
实例
grep "rollback file" /var/log/mongodb/mongod.log
或者,您可以遍历所有数据库并运行db.getCollectionInfos()
以获取特定的UUID,直到找到匹配项。例如
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; } }
回滚数据排除
如果回滚操作是集合删除或文档删除,则不会将集合删除或文档删除的回滚写入回滚数据目录。
读取回滚数据
要读取回滚文件的目录,请使用bsondump
。根据内容和他们的应用知识,管理员可以决定下一步要采取的行动。
避免副本集回滚
对于副本集,写入关注 { w: 1 }
仅提供对主节点的写入操作的确认。如果主节点在写入操作复制到任何副本节点之前崩溃,数据可能会回滚。这包括使用多文档事务提交并使用{ w: 1 }
写入关注写入的数据。
日志记录和写入关注majority
为了防止已确认给客户端的数据回滚,请使用启用日志记录的所有投票成员,并使用{ w: "majority" }写入关注来确保在向发出请求的客户端返回确认之前,写入操作已传播到副本集的大多数节点。
从MongoDB 5.0开始,{ w: "majority" }
是大多数MongoDB部署的默认写入关注。请参阅隐式默认写入关注。
将writeConcernMajorityJournalDefault
设置为false
,MongoDB在确认写入之前不会等待将w: "majority"
写入写入到磁盘日志中。因此,在给定副本集中大多数节点发生短暂丢失(例如,崩溃和重启)的情况下,"majority"
写入操作可能会回滚。
可回滚数据可见性
无论写入的写入关注点如何,使用
"local"
或"available"
读取关注点的其他客户端可以在写入操作被确认之前看到写入操作的结果。使用
"local"
或"available"
读取关注点的客户端可以读取在副本集故障转移期间可能被回滚的数据。
对于多文档事务中的操作,当事务提交时,事务中做出的所有数据更改都会被保存并对外可见。也就是说,事务不会在回滚某些更改的同时提交其他更改。
直到事务提交之前,事务中做出的数据更改在事务外部是不可见的。
然而,当事务写入多个分片时,并非所有外部读取操作都需要等待事务提交的结果在分片之间可见。例如,如果事务已提交,写入1在分片A上可见但写入2在分片B上尚未可见,则在"local"
读取关注点的外部读取可以读取写入1的结果而不看到写入2。
回滚注意事项
用户操作
从版本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中最后一个条目之间的时间。