MongoDB日志记录能保证持久性吗?

MongoDB日志记录能保证持久性吗?,mongodb,Mongodb,即使启用了日志记录功能,是否仍有可能丢失MongoDB中的写操作 默认情况下,最大程度的写操作丢失(即未写入日志的写操作)是在最后100毫秒内完成的写操作 这是从,表示您可能会丢失自上次将日志刷新到磁盘以来所做的写入 如果我想要更持久,“为了强制mongod更频繁地提交日志,可以指定j:true。当带有j:true的写入操作挂起时,mongod会将journalCommitInterval减少到设置值的三分之一。” 即使在这种情况下,将日志刷新到磁盘似乎也是异步的,因此仍有可能丢失写操作。我是否

即使启用了日志记录功能,是否仍有可能丢失MongoDB中的写操作

默认情况下,最大程度的写操作丢失(即未写入日志的写操作)是在最后100毫秒内完成的写操作

这是从,表示您可能会丢失自上次将日志刷新到磁盘以来所做的写入

如果我想要更持久,“为了强制mongod更频繁地提交日志,可以指定j:true。当带有j:true的写入操作挂起时,mongod会将journalCommitInterval减少到设置值的三分之一。”


即使在这种情况下,将日志刷新到磁盘似乎也是异步的,因此仍有可能丢失写操作。我是否遗漏了一些关于如何保证书写不会丢失的信息?

我必须同意Sammaye的观点,即日志记录与耐久性几乎没有关系。但是,如果您想知道是否真的可以信任mongodb以良好的一致性存储数据,那么我建议您阅读本文。有一封来自10gen关于该帖子的回复,还有一封来自作者对10gen帖子的回复。我建议你仔细阅读,做出明智的决定。我自己花了一些时间来理解所有细节,但这篇文章涵盖了基本内容

对这篇博文的回应是,mongodb的生产商

对这个回答的回答是由教授给出的


它解释了很多关于Mongodb如何共享数据、它如何实际工作以及如果您添加额外的安全锁将带来的性能影响。我非常想说的是,这三篇文章是最好的,也是迄今为止讨论mongodb优缺点的最全面的文章,如果你认为它是片面的,看看评论,看看人们都说了些什么,因为如果某个东西收到了软件制造商的回复,那么,它至少也提出了一些好的观点。

也许吧。是的,它等待数据被写入,但是根据文档,有一个,不管是什么。我不知道他们指的是什么

我把经过编辑的答案留在这里,但我前后颠倒了自己,所以有点恼人:


这有点棘手,因为你可以利用很多杠杆:

您的MongoDB设置

假设日志记录已激活(默认为64位),日志将定期提交。如果日志和数据文件位于同一块设备上,则的默认值为100ms;如果不在同一块设备上,则为30ms(因此最好将日志放在单独的磁盘上)

您还可以将日志Commitinterval更改为最短2ms,但这会增加写入操作的数量并降低总体写入性能

写作关注点

您需要指定一个写关注点,告诉驱动程序和数据库等待数据写入磁盘。但是,这不会等到数据实际写入磁盘,因为在默认设置的坏情况下,这需要100毫秒

因此,在最好的情况下,有一个2ms的窗口,数据可能会丢失。然而,这对于许多应用程序来说是不够的

fsync
命令强制对所有数据文件进行磁盘刷新,但如果使用日志记录,这是不必要的,而且效率低下

真实生活耐久性

即使您要记录每一次写入,如果数据中心管理员有一天心情不好,并且在您的硬件上使用了链锯,或者硬件本身就崩溃了,这又有什么好处呢

冗余存储(不是在RAID这样的块设备级别上,而是在更高级别上)对于许多场景来说是一个更好的选择:使用副本集将数据放在不同的位置或至少放在不同的机器上,并在启用日志记录的情况下使用写问题(尽管日志记录只适用于主设备)。在单独的机器上使用RAID来增加你的运气

这提供了性能、耐用性和一致性的最佳折衷。此外,它允许您为每次写入调整写入关注点,并且具有良好的可用性。如果数据在三台不同的机器上排队等待下一个fsync,那么在任何一台机器上进行下一次日志提交可能仍然需要30毫秒(最坏的情况),但三台机器在30毫秒间隔内停机的可能性可能比链锯屠杀管理场景低一百万倍

证据

TL;博士:我想我上面的答案是正确的

文档可能有点烦人,尤其是关于
wtimeout
,所以我检查了源代码。我不是mongo来源方面的专家,所以对此持怀疑态度:

在中,我们发现(为简洁起见进行了编辑):

if(cmdObj[“j”].trueValue()){
如果(!getDur().awaitCommit()){
//--日记本已关闭
结果->追加(“jnote”,“此服务器上未启用日志”);
} // ...
}
else if(cmdObj[“fsync”].trueValue()){
如果(!getDur().awaitCommit()){
//如果你到了这里,不要带着日记跑

log()通常,在每个系统中,如果系统运行时和永久(非易失性)存储之间存在缓冲/缓存/延迟写入,则写丢失是一个问题,即使是在操作系统级别(例如写后缓存)。因此,即使您的具体提供程序(MongoDB),也总是有机会丢失写为事务持久性提供功能—底层操作系统负责最终写入数据,甚至在设备级别上也有缓存……而这只是较低级别的缓存,使系统高度并发、分布式和性能—这只会让事情变得更糟

简言之,没有绝对的耐久性,只有实际的/最终的/希望
if ( cmdObj["j"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // --journal is off
        result->append("jnote", "journaling not enabled on this server");
    } // ...
}
else if ( cmdObj["fsync"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // if get here, not running with --journal
        log() << "fsync from getlasterror" << endl;
        result->append( "fsyncFiles" , MemoryMappedFile::flushAll( true ) );
    }
sleepmillis(oneThird); //dur.cpp, line 801
for( unsigned i = 1; i <= 2; i++ ) {
  // break, if any j:true write is pending
  if( commitJob._notify.nWaiting() )
    break;
  // or the number of bytes is greater than some threshold
  if( commitJob.bytes() > UncommittedBytesLimit / 2  )
    break;
  // otherwise, sleep another third
  sleepmillis(oneThird);
}

// fsync all pending writes                                      
durThreadGroupCommit();