ロールバックは、 フェイルオーバー 後にノードが レプリカセット に再参加したときに、以前の プライマリ での書込み (write) 操作を元に戻します。ロールバックが必要なのは、プライマリが降格する前に、プライマリが受け入れた書込み (write) 操作をセカンダリが正常に 複製できなかった 場合だけです。 プライマリがセカンダリとしてセットに再参加すると、他のノードと間でデータベースの一貫性を維持するために、書込み (write) 操作を元に戻す、つまり "ロールバック" します。
MongoDB はロールバックを回避しようとしますが、これはまれにしか起きないはずです。ロールバックが発生する場合、ネットワーク パーティションが原因の場合が多いです。以前のプライマリの操作スループットに追いつけないセカンダリでは、ロールバックのサイズと影響が大きくなります。
プライマリが降格する前に書込み (write) 操作がレプリカセットの別のノードに複製されて、かつそのノードがレプリカセットの大部分から引き続き使用可能でアクセス可能である場合は、ロールバックは発生しません。
ロールバック データの収集
ロールバック データの設定
createRollbackDataFilesパラメーターは、ロールバック中にロールバック ファイルが作成されるかどうかを制御します。
Rollback Data
デフォルトでは、ロールバックが発生すると、MongoDB はロールバック データを BSON ファイルに書込みます。
データがロールバックされる各コレクションのロールバック ファイルは <dbpath>/rollback/<collectionUUID> ディレクトリにあり、ファイル名は次の形式になります。
removed.<timestamp>.bson
たとえば、reporting データベース内のコレクション comments のデータがロールバックされた場合、ファイルの場所は以下の通りです。
<dbpath>/rollback/20f74796-d5ea-42f5-8c95-f79b39bad190/removed.2020-02-19T04-57-11.0.bson
ここで、<dbpath>は mongod の dbPath です。
Tip
コレクション名
コレクション名を取得するには、MongoDB ログで rollback file を検索します。たとえば、ログファイルが /var/log/mongodb/mongod.log の場合、grep を使用して、ログ内で "rollback file" のインスタンスを検索できます。
grep "rollback file" /var/log/mongodb/mongod.log
あるいは、すべてのデータベースでループ処理を行い、一致するまで特定の UUID に対して db.getCollectionInfos() を実行してすることもできます。以下に例を挙げます。
var mydatabases=db.adminCommand("listDatabases").databases; var foundcollection=false; for (var i = 0; i < mydatabases.length; i++) { let mdb = db.getSiblingDB(mydatabases[i].name); collections = mdb.getCollectionInfos( { "info.uuid": UUID("20f74796-d5ea-42f5-8c95-f79b39bad190") } ); for (var j = 0; j < collections.length; j++) { // Array of 1 element foundcollection=true; print(mydatabases[i].name + '.' + collections[j].name); break; } if (foundcollection) { break; } }
ロールバック データの除外
ロールバックする操作がコレクション削除またはドキュメント削除の場合、コレクション削除やドキュメント削除のロールバックはロールバック データディレクトリに書込まれません。
警告
書込み操作で{ w: 1 }書込み保証が使用される場合、書込み操作が完了する前にプライマリが再起動すると、ロールバック ディレクトリはoplog hole後に送信された書込みを除外することがあります。
ロールバック データの読み取り
ロールバック ファイルの内容を読み取るには、bsondump を使用します。管理者は、ファイルの内容と、アプリケーションに関する知識に基づいて、次に取るべきアクションを決定できます。
レプリカセットのロールバックの回避
レプリカセットの場合、書込み保証 (write concern) { w: 1 } では、プライマリでの書込み (write) 操作の確認のみを提供します。書込み (write) 操作がいずれかのセカンダリに複製される前にプライマリが降格した場合、データはロールバックされる可能性があります。これには、{ w: 1 } 書込み保証 (write concern) を使用してコミットするマルチドキュメントトランザクションで書き込まれたデータが含まれます。
ジャーナリングと書込み保証 (write concern) majority
クライアントに確認応答されたデータのロールバックを防ぐには、ジャーナリングを有効にして投票権を持つすべてのノードを実行し、{ w: "majority" } 書込み保証 (write concern) を使用して、書込み (write) 操作がレプリカセットのノードの過半数に伝播してから、発行元のクライアントへ確認応答を返すようにします。
MongoDB 5.0 以降では、ほとんどのMongoDB 配置で { w: "majority" } がデフォルトの書込み保証 (write concern) です。「暗黙のデフォルト書込み保証 (write concern)」を参照してください。
writeConcernMajorityJournalDefault を false に設定すると、MongoDB は書き込みを確認する前に、オンディスク ジャーナルに w: "majority" 書き込みが書き込まれるのを待たなくなります。そのため、"majority" 特定のレプリカセット内の大多数のノードでの一時的な損失(例: クラッシュおよび再起動)が発生したイベントにロールバックされる可能性があります。
ロールバック可能なデータの可視性
書き込み (write) の書込み保証 (write concern) に関係なく、
"local"または"available"の読み取り保証 (read concern) を使用する他のクライアントは、書き込み (write) 操作が発行クライアントに確認される前に、書き込み (write) 操作の結果を確認できます。"local"または"available"読み取り保証 (read concern)を使用するクライアントは、レプリカセットのフェイルオーバー中に、後でロールバックされる可能性のあるデータを読み取ることができます。
マルチドキュメントトランザクションの操作では、トランザクションがコミットされると、トランザクション内のすべてのデータ変更が保存され、トランザクションの外部に表示されます。つまり、トランザクションが他の変更をロールバックしながら、一部の変更をコミットすることはありません。
トランザクションがコミットされるまで、トランザクションで行われたデータ変更はトランザクションの外部には表示されません。
ただし、トランザクションが複数のシャードに書き込む場合、すべての外部読み取り操作が、コミットされたトランザクションの結果がシャード全体で表示されるまで待機する必要はありません。たとえば、トランザクションがコミットされ、書込み 1 がシャード A で表示されているものの、書込み 2 がシャード B にまだ表示されていない場合、読み取り保証(read concern) "local" での外部読み取りは、書き込み 2 を見ることなく書き込み 1 の結果を読み取ることができます。
ロールバックに関する考慮事項
ユーザー操作
バージョン 4.2 以降、MongoDB はノードが ROLLBACK 状態になると、進行中のすべてのユーザー操作を強制終了します。
インデックス構築
機能の互換性バージョン(fcv)
"4.2"の場合、MongoDB はロールバックを開始する前に、進行中のインデックス構築が完了するまで待機します。
インデックス構築プロセスの詳細については、「入力済みコレクションでのインデックス構築」を参照してください。
"majority"読み取り保証が無効の場合のインデックス操作
"majority" 読み取り保証 (read concern) を無効にすると、MongoDB はインデックスを変更する collMod コマンドのロール バックを防ぎます。collMod コマンドをロール バックする必要がある場合、影響を受けたノードをプライマリ ノードと再同期する必要があります。
サイズ制限
MongoDB は、サイズ制限が異なる次のロールバック アルゴリズムをサポートしています。
タイムスタンプに回復。以前のプライマリは一貫性のある時点まで戻り、同期ソースの履歴ブランチに追いつくまで操作を適用します。これがデフォルトのロールバック アルゴリズムです。
このアルゴリズムを使う場合、MongoDB はロールバックできるデータ量を制限しません。
Refetch によるロールバック。以前のプライマリは、自分のoplogと同期ソースの oplog 間の共通点を見つけます。次に、ノードが oplog 内のすべての操作を検査し、この共通点に達するまで元に戻します。Refetch によるロールバックは、設定ファイルの
enableMajorityReadConcern設定がfalseに設定されている場合にのみ発生します。このアルゴリズムを使用する場合、MongoDB がロールバックできるデータは最大 300 MB です。
注意
MongoDB 5.0 以降では、
enableMajorityReadConcernはtrueに設定されており、変更できません。
ロールバック経過時間の制限
ロールバックの時間制限はデフォルトで 24 時間であり、rollbackTimeLimitSecs パラメーターを使用して設定できます。
MongoDB は、oplog 内の最初の一般的な操作から、ロールバックされるノードによる oplog の最後のエントリまでの時間として経過時間を測定します。