即使启用日记功能,MongoDB中仍有机会丢失写入内容吗?
"默认情况下,最大程度的丢失写入,即那些没有写入日志的写入,是在过去100毫秒内完成的."
这来自Manage Journaling,它表示自上次将日志刷新到磁盘后可能会丢失写入.
如果我想要更强的持久性,"为了强制mongod更频繁地提交日志,你可以指定j:true.当j:true的写操作挂起时,mongod会将journalCommitInterval减少到设定值的三分之一."
即使在这种情况下,看起来将日志刷新到磁盘也是异步的,因此仍有机会丢失写入.我错过了一些关于如何保证写入不会丢失的内容吗?
mne*_*syn 19
发布一个新答案来清理它.我进行了测试并再次阅读了源代码,我确信这种烦恼来自写作问题文档中的一个不幸的句子.在启用日记功能和j:true写入问题的情况下,写入是持久的,并且没有神秘的数据丢失窗口.
即使启用日记功能,MongoDB中仍有机会丢失写入内容吗?
是的,因为耐久性还取决于个人操作所关注的问题.
"默认情况下,最大程度的丢失写入,即那些没有写入日志的写入,是在过去100毫秒内完成的."
这来自Manage Journaling,它表示自上次将日志刷新到磁盘后可能会丢失写入.
那是正确的.日志被异步刷新一个单独的线程,因此自上次刷新后您可能会丢失所有内容.
如果我想要更多的持久性,"要强制mongod更频繁地提交日志,你可以指定
j:true.当一个写入操作处于j:true暂挂状态时,mongod将减少journalCommitInterval到设定值的三分之一."
这也激怒了我.这就是它的含义:
当您发送写入操作时j:true,它不会立即触发磁盘刷新,而不会在网络线程上触发.这是有道理的,因为可能有数十个应用程序与同一个mongod实例进行通信.如果每个应用程序都经常使用日志,那么db会非常慢,因为它一直都在使用.
相反,会发生的是'持久性线程'将采用所有挂起的日志提交并将它们刷新到磁盘.线程是这样实现的(评论我的):
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();
Run Code Online (Sandbox Code Playgroud)
因此,挂起的j:true操作将导致日志提交线程比通常更早地提交,并且它将提交对日志的所有挂起写入,包括那些没有j:true设置的日志.
即使在这种情况下,看起来将日志刷新到磁盘也是异步的,因此仍有机会丢失写入.我错过了一些关于如何保证写入不会丢失的内容吗?
getLastError带有j:true日志写入问题的写入(或命令)将等待持久性线程完成同步,因此不存在数据丢失的风险(就OS和硬件保证而言).
句子"但是,当写入操作不完全持久时,日志提交之间有一个窗口"可能是指运行启用了日记功能的mongod接受不使用j:true写入关注的写入.在这种情况下,自上次提交日志以来,写入可能会丢失.
我为此提交了一份文档错误报告.
我必须同意 Sammaye 的观点,即日记与持久性没有什么关系。但是,如果您想得到是否真的可以信任 mongodb 能够以良好的一致性存储数据的答案,那么我建议您阅读这篇博文。有 10gen 对该帖子的回复,以及作者对 10gen 帖子的回复。我建议您仔细阅读以做出明智的决定。我花了一些时间自己理解所有细节,但这篇文章涵盖了基础知识。
制作 mongodb 的公司10gen 对此博文做出了回应。
而教授在这个帖子上也给出了回应。
它解释了很多关于 Mongodb 如何对数据进行分片、它的实际功能以及添加额外的安全锁时所需的性能影响。我强烈想说,这三篇文章是目前为止讲MongoDB优缺点最全面的东西,如果你觉得它片面,看看评论,也看看人们必须说的话,因为如果某个东西收到了软件制作公司的回复,那么它至少肯定提出了一些好的观点。
| 归档时间: |
|
| 查看次数: |
5439 次 |
| 最近记录: |