Mongodbのドキュメントでは、次のように書かれています。
バージョン2.2以降、MongoDBは、ほとんどの読み取りおよび書き込み操作に対してデータベースごとにロックを実装します。一部のグローバル操作、通常は複数のデータベースを含む短命の操作では、グローバルな「インスタンス」ワイドロックが必要です。 2.2より前では、mongodインスタンスごとに「グローバル」ロックは1つしかありません。
これは、たとえば、ネットワーク上で実行されているさまざまなアプリからmongodb:// localhost/testへの接続が3つあるという状況では、一度に1つしか書き込みできないことを意味しますか?それとも接続ごとですか?
IOW:接続ごとですか、または書き込み中に/ testデータベース全体がロックされていますか?
接続ごとではなく、mongod
ごとです。つまり、そのサーバー上のtest
データベースへのすべての接続にロックが存在します。
また、読み取り/書き込みロックなので、書き込みが発生している場合は読み取りを待機する必要があります。
ただし、MongoDBロックは、取得するSQL /通常のトランザクションロックとは非常に異なり、通常、平均更新の間に約1秒間ロックが保持されます。
MongoDBでのロックは、RDBMSでのロックのようには機能しないため、少し説明が必要です。 MongoDBの以前のバージョンでは、単一のグローバルリーダー/ライターラッチがありました。 MongoDB 2.2以降では、各データベースにリーダー/ライターラッチがあります。
ラッチは、マルチリーダー、シングルライターであり、ライター欲張りです。この意味は:
これを「ロック」ではなく「ラッチ」と呼ぶことに注意してください。これは、軽量であり、適切に設計されたスキーマでは、書き込みロックが数十マイクロ秒のオーダーで保持されるためです。リーダーライターのロックの詳細については、 here を参照してください。
MongoDBでは、必要な数のクエリを同時に実行できます。関連データがRAMにある限り、ロック競合なしですべて満たされます。
MongoDBでは、トランザクションのレベルは単一のドキュメントであることを思い出してください。 1つのドキュメントに対するすべての更新はアトミックです。 MongoDBは、RAM内の1つのドキュメントを更新するのに必要な時間だけ書き込みラッチを保持することでこれを実現します。低速の操作がある場合(特に、ドキュメントまたはインデックスエントリをディスクからページインする必要がある場合)、その操作はyield書き込みラッチ。操作がラッチを生成すると、次のキュー操作が続行できます。
これは、単一のデータベース内のすべてのドキュメントへの書き込みがシリアル化されることを意味します。スキーマの設計が貧弱で、書き込みに時間がかかる場合、これは問題になる可能性がありますが、適切に設計されたスキーマでは、ロックは問題になりません。
作家貪欲であることに関するいくつかの言葉:
一度にラッチを保持できるライターは1人だけです。一度に複数のリーダーがラッチを保持できます。単純な実装では、単一のリーダーが動作している場合、ライターは無期限に飢えてしまう可能性があります。これを避けるため、MongoDB実装では、1つのスレッドが特定のラッチに対して書き込み要求を行うと、
この作家の貪欲な振る舞いは、非自明な方法で譲歩と相互作用するため、実際の振る舞いは複雑です。リリース2.2以降では、各データベースにseparateラッチがあるため、データベース 'A'のコレクションへの書き込みは個別のラッチを取得することを思い出してください。データベース「B」の任意のコレクションに書き込むよりも。
特定の質問について:
これはパフォーマンス上の大きな懸念事項のように聞こえますが、実際には速度を落とすことはありません。適切に設計されたスキーマと典型的なワークロードにより、MongoDBは、データベースのロック率が50%を超える前に、SSDであってもディスクI/O容量を飽和させます。
私が知っている最大容量のMongoDBクラスターは、現在1秒あたり200万回の書き込みを実行しています。
Mongo 3.0は、コレクションレベルのロックをサポートするようになりました。
これに加えて、Mongoはストレージエンジンを作成できるAPIを作成しました。 Mongo 3.0には2つのストレージエンジンが付属しています。
私は質問がかなり古いことを知っていますが、それでも一部の人々は混乱しています...
MongoDB 3.0以降では、WiredTigerストレージエンジン(document-level concurrencyを使用)は64ビットビルドで使用できます。
WiredTigerは、書き込み操作にドキュメントレベルの同時実行制御を使用します。その結果、複数のクライアントがコレクションの異なるドキュメントを同時に変更できます。
ほとんどの読み取りおよび書き込み操作では、WiredTigerはオプティミスティック同時実行制御を使用します。 WiredTigerは、グローバル、データベース、およびコレクションレベルでインテントロックのみを使用します。ストレージエンジンが2つの操作間の競合を検出すると、書き込みの競合が発生し、MongoDBがその操作を透過的に再試行します。
一部のグローバル操作、通常は複数のデータベースを含む短命の操作では、グローバルな「インスタンス全体」のロックが必要です。コレクションの削除など、その他の一部の操作では、引き続きデータベースの排他ロックが必要です。