これをクリーンアップするための新しい回答を投稿します。私はテストを実行し、ソースコードをもう一度読みましたが、書き込みに関するドキュメントの不幸な文章が原因であると確信しています。ジャーナリングが有効で、j:true
書き込みの懸念、書き込みは耐久性があり、データ損失の不思議なウィンドウはありません。
ジャーナリングがオンになっている場合でも、MongoDBへの書き込みが失われる可能性はありますか?
はい、耐久性は個々の操作の書き込みの懸念にも依存するためです。
「デフォルトでは、失われた書き込みの最大の範囲、つまりジャーナルに対して行われなかったものは、過去100ミリ秒に行われたものです。」
これは、ジャーナルの管理からのものです。これは、ジャーナルが最後にディスクにフラッシュされてから行われた書き込みが失われる可能性があることを示しています。
それは正しいです。ジャーナルは別のスレッドによって非同期的にフラッシュされるため、最後のフラッシュ以降にすべてが失われる可能性があります。
より耐久性が必要な場合は、「mongodにジャーナルへのコミットをより頻繁に強制するには、
j:true
を指定できます。 。j:true
を使用した書き込み操作の場合 保留中の場合、mongodはjournalCommitInterval
を削減します 設定値の3分の1に。」
これも私を苛立たせました。意味は次のとおりです。
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();
したがって、保留中のj:true
操作により、ジャーナルコミットスレッドは通常よりも早くコミットされ、j:true
を持たないものも含め、ジャーナルへの保留中のすべての書き込みがコミットされます。 セット。
この場合でも、ジャーナルのディスクへのフラッシュは非同期であるように見えるため、書き込みが失われる可能性があります。書き込みが失われないことを保証する方法について何かが足りませんか?
書き込み(またはgetLastError
コマンド)j:true
を使用 ジャーナル書き込みの懸念事項は、耐久性スレッドの同期が完了するのを待ちます 、したがって、データ損失のリスクはありません(OSとハードウェアがそれを保証する限り)。
「ただし、書き込み操作が完全に耐久性がない場合、ジャーナルのコミット間にウィンドウがあります」という文は、ジャーナルを有効にして実行され、しない書き込みを受け入れるmongodを指している可能性があります。 j:true
を使用します 懸念を書いてください。その場合、最後のジャーナルコミット以降に書き込みが失われる可能性があります。
このためのドキュメントバグレポートを提出しました。