隔離保証
読み取りコミットなし
読み取り保証(read concern)に応じて、クライアントは、書込みが 耐久性を持つ前に、書込みの結果を確認できます。
書込み(write)の書込み保証(write concern)に関係なく、
"local"または"available"の読み取り保証(read concern)を使用する他のクライアントは、書込み(write)操作が発行クライアントに確認される前に、書込み(write)操作の結果を確認できます。"local"または"available"読み取り保証(read concern)を使用するクライアントにより、後でレプリカセットのフェイルオーバー中にロールバックされる可能性があるデータを読み取れます。
マルチドキュメントトランザクションの操作では、トランザクションがコミットされると、トランザクション内のすべてのデータ変更が保存され、トランザクションの外部に表示されます。つまり、トランザクションが他の変更をロールバックしながら、一部の変更をコミットすることはありません。
トランザクションがコミットされるまで、トランザクションで行われたデータ変更はトランザクションの外部には表示されません。
ただし、トランザクションが複数のシャードに書き込む場合、すべての外部読み取り操作が、コミットされたトランザクションの結果がシャード全体で表示されるまで待機する必要はありません。たとえば、トランザクションがコミットされ、書込み 1 がシャード A で表示されているものの、書込み 2 がシャード B にまだ表示されていない場合、読み取り保証(read concern) "local" での外部読み取りは、書き込み 2 を見ることなく書き込み 1 の結果を読み取ることができます。
読み取りコミットなしとは、デフォルトの分離レベルであり、mongod のスタンドアロンインスタンス、レプリカセット、シャーディングされたクラスターに適用されます。
読み取りコミットなしと単一ドキュメントの不可分性
書き込み操作は単一のドキュメントに対してアトミックです。つまり、書き込みがドキュメント内の複数のフィールドを更新する場合、読み取り操作では一部のフィールドのみが更新されたドキュメントが表示されることはありません。ただし、 クライアントには部分的にアップデートされたドキュメントは表示されない場合がありますが 、読み取りコミットがない場合は、同時に実行された読み取り操作でも、変更が永続化される前に更新されたドキュメントが表示される可能性があります。
スタンドアロンの mongod インスタンスでは、1 つのドキュメントに対する一連の読み取り操作と書込み操作をシリアル化できます。レプリカセットでは、1つのドキュメントに対する一連の読み取りおよび書込み操作をシリアル化できるのは、ロールバックがない場合だけです。
読み取りコミットなしと複数ドキュメントの書込み
単一の書込み操作(例: db.collection.updateMany())は複数のドキュメントを変更します。各ドキュメントの変更は不可分ですが、操作全体は不可分ではありません。
複数のドキュメントへの書込み操作を実行する場合、1 回の書込み操作でも複数の書込み操作でも、他の操作がインターリーブすることがあります。
MongoDB は(単一または複数のコレクション内の)複数のドキュメントへの読み取りと書込みにアトミック性を必要とする状況で、レプリカセットやシャーディングされたクラスターでのトランザクションを含む分散トランザクションをサポートします。
詳細については、「トランザクション」を参照してください。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
マルチドキュメントの書込み操作を分離しない場合、MongoDB は次の動作を示します。
非ポイント・イン・タイム読み取り操作。ドキュメントの読み取り操作が時刻t 1に開始されるとします。その後、書込み操作によって、後の時間 t 2 にドキュメントの 1 つに対する更新がコミットされます。読者はドキュメントの更新されたバージョンを参照できますが、データの特定時点のスナップショットは参照できません。
シリアル化できない操作。読み取り操作によってドキュメント d 1 が時刻 t 1 に読み取られ、書込み操作によってその後の時刻 t 3 に d 1 が更新されるとします。これにより、読み取りと書込みの依存関係が導入され、操作をシリアル化する場合、読み取り操作が書込み操作に先行する必要があります。しかし、書込み操作によってドキュメント d 2 が時刻 t 2 に更新され、その後読み取り操作によって時刻 t 4 に d 2 が読み取られるとします。これにより、書込みと読み取りの依存関係が導入され、シリアル化可能なスケジュールで読み取り操作が書込み操作の後に実行されることが必要になります。依存関係のサイクルが存在するため、シリアル化が不可能になります。
読み取り操作の過程で更新された一致するドキュメントが読み取られない場合があります。
カーソルのスナップショット
MongoDB カーソルは、状況によっては、同じドキュメントを複数回返すことがあります。カーソルによってドキュメントが返されると、他の操作がクエリとインターリーブする可能性があります。これらの操作のいずれかによって、クエリで使用されるインデックスのインデックス付きフィールドが変更されると、カーソルは同じドキュメントを複数回返す可能性があります。
ユニークインデックスを使用するクエリでは、重複した値が返される場合があります。ユニークインデックスを使用するカーソルが、同じユニークな値を共有するドキュメントの削除と挿入をインターリーブする場合、カーソルは異なるドキュメントから同じユニークな値を 2 回返すことがあります。
整合性を向上させるために、読み取り分離を使用します。詳しくは、読み取り保証(read concern) "snapshot" を参照してください。
単調書込み
MongoDBは、スタンドアロンのmongodインスタンスとレプリカセットに対して、デフォルトで単調な書き込み保証を提供します。
単調な書込みとシャーディングされたクラスターについては、 因果整合性を参照してください。
ドキュメントを変更しない書き込みは、ノーオペレーション noop書き込みと呼ばれます。ノーオペレーション書き込み:
書き込みのフィルターがどのドキュメントにも一致しない場合、または書き込みを適用した後に一致したドキュメントが変更されない場合に発生します。
optime値を増やさないでください。
0に等しいWriteResult.nModifiedが返され、書き込み (write)操作によりドキュメントが修正されなかったことを示します。
操作なし書き込みで単調性を確保するには、 因果整合性の保証 を使用します。その他のすべての書き込み (write) について、次のセクションでは単調性の保証について説明します。
リアルタイム注文
プライマリでの読み取りおよび書込み操作では、読み取りには"linearizable"読み取り保証 (read concern)を発行し、書込みには"majority"書込み保証 (write concern)を発行すると、複数のスレッドが 1 つのドキュメントを読み書きできるようになります。これらの操作は 1 つのスレッドがリアルタイムで実行したようにします。これらの読み取りと書込みの結果として得られるスケジュールは線形化可能です。
Tip
因果整合性
先行する操作に論理的に依存する操作には 因果関係があります。例、指定された条件に一致するすべてのドキュメントを削除する書込みと、削除操作を検証する後続の読み取りには、 因果関係があります。
因果的にコンシステントなセッションでは、 MongoDB は因果関係を尊重する順序で因果操作を実行します。クライアントは、これらの関係と一貫性のある結果を観察します。
クライアント セッションと因果整合性の保証
MongoDB はクライアントセッションを通じて因果整合性を有効にします。因果整合性のあるセッションにより、"majority" 読み取り保証 (read concern)を持つ読み取り操作と "majority" 書込み保証 (write concern)を持つ書込み操作に、順序付けに反映される因果関係が必要になります。 アプリケーションでは、クライアントセッションで一度に 1 つのスレッドのみがこれらの操作が実行されるようにする必要があります。
因果関係のある操作の場合:
クライアントがクライアント セッションを開始します。
重要
クライアント セッションでは、次の因果整合性のみが保証されます。
"majority"読み取り保証 (read concern)による読み取り操作。返されたデータは、レプリカセットの過半数によって確認されており、耐久性があります。"majority"書込み保証 (write concern)による書込み操作。これらの操作は、レプリカセットの投票ノードの過半数に書き込み (write) が適用されたことの確認応答をリクエスト。
因果関係の一貫性と読み取りと書込み保証(write concern)に関するさまざまな問題について詳しくは、「因果整合性、読み取り保証、書込み保証」を参照してください。
クライアントが
"majority"読み取り保証 (read concern)を持つ読み取り操作と、"majority"書込み保証 (write concern)を持つ書込み操作を発行するため、クライアントは各操作にセッション情報を含めることができます。セッションに関連付けられた
"majority"読み取り保証 (read concern)持つ読み取り操作と"majority"書込み保証 (write concern)を持つ書込み操作ごとに、操作にエラーがあった場合でも、 MongoDB は操作時間とクラスター時間を返します。クライアントセッションは操作時間とクラスター時間を追跡します。注意
MongoDB では、未確認の(
w: 0)書込み操作の操作時間とクラスター時間が返されません。未確認の書込みは、因果関係を意味するものではありません。MongoDB は、クライアントセッションでの読み取り操作と確認済みの書き込み (write) 操作の operation time とクラスター時間を返します。因果整合性が保証されるのは、
"majority"読み取り保証 (read concern)を持つ読み取り操作と"majority"書込み保証 (write concern)を持つ書込み操作のみです。詳細については、因果整合性、読み取り保証、書込み保証 (write concern) を参照してください。関連付けられているクライアント セッションは、これら 2 つの時間フィールドを追跡します。
注意
異なるセッション間でも、操作は因果的にコンシステントである場合があります。MongoDBドライバーと
mongoshは、クライアントセッションの操作時間とクラスター時間を進めるメソッドを提供します。クライアントは、1 つのクライアントセッションのクラスター時間とoperation timeを、別のクライアントセッションの操作とコンシステントになるように進めることができます。
因果整合性の保証
次の表では、読み取り操作には "majority" 読み取り保証 (read concern)を使用し、 書込み操作には "majority" 書込み保証 (write concern)を使用する因果整合性のあるセッションの因果整合性の保証について説明しています。
保証 | 説明 |
|---|---|
書込み操作の結果を読み取る | 読み取り操作は、その前の書込み操作の結果を反映します。 |
単調な読み取り | 読み取り操作では、前の読み取り操作よりも前のデータの状態に対応する結果は返されません。 たとえば、セッション中の場合:
そのため、読み取り2は書込み1の結果を返すことができません。 |
単調書込み | 他の書込みに優先する必要がある書込み操作は、他の書込みの前に実行する必要があります。 たとえば、セッションで書込み1が書込み2に優先する必要がある場合、書込み2の時点でのデータの状態は、書込み1後のデータの状態を反映している必要があります。書込み1と書込み2の間で他の書込みをインターリーブすることはできますが 、 書込み1の前に書込み2を行うことはできません 。 |
書込み操作の前に読み取り操作をする | 読み取り操作の後に実行する必要がある書込み操作は、それらの読み取り操作の後に実行されます。つまり、書込み時のデータの状態には、前の読み取り操作のデータの状態が反映されている必要があります。 |
読み込み設定 (read preference)
これらの保証は、 MongoDB配置のすべてのノードに適用されます。例、因果関係が整合しているセッションで、"majority" 書込み保証 (write concern)を持つ書き込みを実行した後に、読み込み設定 (read preference) secondary と "majority" 読み取り保証 (read concern)を持つセカンダリからの読み取りを実行すると、読み取り操作には次のデータベースの状態が反映されます:書き込み (write)操作。
分離
因果的に整合したセッション内の操作は、セッション外の操作から分離されません。セッションの書込み操作と読み取り操作の間に同時書込み操作が交互に行われる場合、セッションの読み取り操作は、セッションの書込み操作の後に発生した書込み操作を反映した結果を返すことがあります。
MongoDB ドライバー
Tip
アプリケーションでは、クライアント セッションで一度に 1 つのスレッドのみがこれらの操作が実行されるようにする必要があります。
クライアントには、MongoDB 3.6 以降用の最新 MongoDB ドライバーが必要です。
Java 3.6+ Python 3.6+ C 1.9+ Go 1.8+ | C# 2.5+ Node 3.0+ Ruby 2.5+ Rust 2.1+ Swift 1.2+ | Perl 2.0+ PHPC 1.4+ Scala 2.2+ C++ 3.6.6+ |
例
重要
因果的に整合性のあるセッションでは、"majority" 読み取り保証 (read concern)を持つ読み取りと "majority" 書込み書込み保証 (write concern)のある書込みに対してのみ因果整合性が保証されます。
さまざまな項目の現在のデータと履歴データを保持するコレクションitems について考えてみましょう。履歴データのみに null 以外の end 日付があります。アイテムの sku 値が変更された場合は、古い sku 値でドキュメントを更新して end 日付を追加し、現在の sku 値を持つ新しいドキュメントを挿入します。因果的にコンシステントなセッションを使用して、挿入の前に更新が行われるようにします。
言語セレクターを使用して、この例の言語を設定します。
現在のすべての sku 値を別のクライアントから読み取るには、クラスター時間と operation time を他のセッションに一致するように進める必要があります。これにより、クライアントは他のセッションと因果的にコンシステントであり、2 回の書き込み後に読み取ることができます。
制限
次の操作はメモリ内構造を構築しますが、因果的にコンシステントではありません。
操作 | ノート |
|---|---|
| |
操作に因果整合性があるクライアント セッションに関連付けられている場合はエラーを返します。 | |
操作に因果整合性があるクライアント セッションに関連付けられている場合はエラーを返します。 | |
操作に因果整合性があるクライアント セッションに関連付けられている場合はエラーを返します。 | |
操作に因果整合性があるクライアント セッションに関連付けられている場合はエラーを返します。 | |