MongoDBのロックは異なります
MongoDBでのロックは、RDBMSでのロックのようには機能しないため、少し説明が必要です。以前のバージョンのMongoDBには、単一のグローバルリーダー/ライターラッチがありました。 MongoDB 2.2以降、データベースごとにリーダー/ライターラッチがあります。
リーダー-ライターラッチ
ラッチはマルチリーダー、シングルライターであり、ライターに貪欲です。これは次のことを意味します:
- データベースには無制限の数の同時リーダーが存在する可能性があります
- 1つのデータベースのコレクションには、一度に1人のライターしか存在できません(これについては後で詳しく説明します)
- ライターはリーダーをブロックします
- 「writer-greedy」とは、書き込み要求が受信されると、書き込みが完了するまですべてのリーダーがブロックされることを意味します(これについては後で詳しく説明します)
これを「ロック」ではなく「ラッチ」と呼んでいることに注意してください。これは、軽量であり、適切に設計されたスキーマでは、書き込みロックが数十マイクロ秒程度に保持されるためです。リーダーとライターのロックの詳細については、こちらをご覧ください。
MongoDBでは、必要な数のクエリを同時に実行できます。関連するデータがRAMにある限り、競合をロックすることなくすべてが満たされます。
アトミックドキュメントの更新
MongoDBでは、トランザクションのレベルは単一のドキュメントであることを思い出してください。 1つのドキュメントに対するすべての更新はAtomicです。 MongoDBは、RAM内の単一のドキュメントを更新するのにかかる時間だけ書き込みラッチを保持することでこれを実現します。実行速度の遅い操作がある場合(特に、ドキュメントまたはインデックスエントリをディスクからページインする必要がある場合)、その操作は歩留まりになります。 書き込みラッチ。操作がラッチを生成すると、次にキューに入れられた操作を続行できます。
これは、単一のデータベース内のすべてのドキュメントへの書き込みがシリアル化されることを意味します。これは、スキーマの設計が不十分で書き込みに時間がかかる場合に問題になる可能性がありますが、適切に設計されたスキーマでは、ロックは問題になりません。
ライター-貪欲
作家欲張りであることについてのもう少しの言葉:
一度にラッチを保持できるのは1人のライターだけです。複数のリーダーが一度にラッチを保持できます。単純な実装では、動作中のリーダーが1つしかない場合、ライターは無期限に飢餓状態になる可能性があります。これを回避するために、MongoDBの実装では、単一のスレッドが特定のラッチの書き込み要求を行うと
- そのラッチを必要とする後続のすべてのリーダーはブロックされます
- そのライターは、現在のすべてのリーダーが終了するまで待機します
- ライターは書き込みラッチを取得し、その作業を行ってから、書き込みラッチを解放します
- キューに入れられたすべてのリーダーが続行します
このライター欲張りな振る舞いは、自明ではない方法で譲歩と相互作用するため、実際の振る舞いは複雑です。リリース2.2以降、別のがあることを思い出してください。 データベースごとにラッチするため、データベース「A」のコレクションへの書き込みは、データベース「B」のコレクションへの書き込みとは別のラッチを取得します。
具体的な質問
具体的な質問について:
- ロック(実際にはラッチ)は、単一のドキュメントを更新するのにかかる時間だけ、MongoDBカーネルによって保持されます
- MongoDBに複数の接続があり、それぞれが一連の書き込みを実行している場合、その書き込みが完了するまでの間、データベースごとにラッチが保持されます
- 書き込み(更新/挿入/削除)の実行時に発生する複数の接続はすべてインターリーブされます
これはパフォーマンス上の大きな懸念事項のように聞こえますが、実際には速度が低下することはありません。適切に設計されたスキーマと一般的なワークロードを使用すると、MongoDBは、データベースのロック率が50%を超える前に、SSDの場合でもディスクI/O容量を飽和させます。
私が知っている最大容量のMongoDBクラスターは、現在1秒あたり200万回の書き込みを実行しています。