sql >> データベース >  >> NoSQL >> MongoDB

MongoDBで最近削除されたドキュメントを回復する方法はありますか?

    ロールバックオプションはありません(ロールバックはMongoDBコンテキストでは異なる意味を持ちます)。厳密に言えば、これらのドキュメントを元に戻すためのサポートされている方法はありません。注意事項はコメントで説明されています。ただし、レプリカセットを実行している場合は、単一ノードのレプリカセットであっても、oplogがあります。 。 oplogを使用 ドキュメントが挿入された時期をカバーしているので、ドキュメントを復元できる可能性があります。

    これを説明する最も簡単な方法は、例を使用することです。復元する必要のある削除されたドキュメントを100個だけ使用した単純化された例を使用します。これを超えるには(膨大な数のドキュメント、または選択的にのみ復元したいなど)、コードを変更してカーソルを反復処理するか、MongoDBシェルの外部で選択した言語を使用してこれを記述します。基本的なロジックは同じです。

    まず、サンプルコレクションfooを作成しましょう データベース内dropTestnameなしで100個のドキュメントを挿入します フィールドと同じnameの100個のドキュメント 後で誤って削除できるようにフィールド:

    use dropTest;
    for(i=0; i < 100; i++){db.foo.insert({_id : i})};
    for(i=100; i < 200; i++){db.foo.insert({_id : i, name : "some_x_name"})};
    

    それでは、100個のnameの誤った削除をシミュレートしてみましょう。 ドキュメント:

    > db.foo.remove({ "name" : "some_x_name"})
    WriteResult({ "nRemoved" : 100 })
    

    レプリカセットで実行しているため、これらのドキュメントの記録はoplogに残っています。 (挿入されている)そしてありがたいことに、それらの挿入は(まだ)oplogの終わりから落ちていません (oplog 上限のあるコレクションです覚えています)。それらを見つけることができるかどうか見てみましょう:

    use local;
    db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}).count();
    100
    

    カウントは正しいようですが、ドキュメントはまだ残っているようです。私は経験から、oplogの唯一の部分であることを知っています ここで必要なエントリはoです フィールドなので、それだけを返すようにプロジェクションを追加しましょう(簡潔にするために出力を切り取ったものですが、わかります):

    db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}, {"o" : 1});
    { "o" : { "_id" : 100, "name" : "some_x_name" } }
    { "o" : { "_id" : 101, "name" : "some_x_name" } }
    { "o" : { "_id" : 102, "name" : "some_x_name" } }
    { "o" : { "_id" : 103, "name" : "some_x_name" } }
    { "o" : { "_id" : 104, "name" : "some_x_name" } }
    

    これらのドキュメントを再挿入するには、それらを配列に格納してから、配列を繰り返し処理して、関連する部分を挿入します。まず、配列を作成しましょう:

    var deletedDocs = db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}, {"o" : 1}).toArray();
    > deletedDocs.length
    100
    

    次に、コレクションには現在100個のドキュメントしかないことを思い出し、100個の挿入をループして、最後にカウントを再検証します。

    use dropTest;
    db.foo.count();
    100
    // simple for loop to re-insert the relevant elements
    for (var i = 0; i < deletedDocs.length; i++) {
        db.foo.insert({_id : deletedDocs[i].o._id, name : deletedDocs[i].o.name});
    }
    // check total and name counts again
    db.foo.count();
    200
    db.foo.count({name : "some_x_name"})
    100
    

    そして、いくつかの注意点がありますが、それがあります:

    • コメントに記載されているように、これは真の復元戦略を意味するものではありません。バックアップ(MMS、その他)、そのための遅延セカンダリを確認してください。
    • 大規模なビジー状態のシステムでは、oplogからドキュメントをクエリするのは特に迅速ではありません(oplogクエリはテーブルスキャンです)。
    • ドキュメントはいつでもoplogから古くなる可能性があります(もちろん、後で使用するためにoplogのコピーを作成して、より多くの時間を与えることができます)
    • ワークロードによっては、結果を再挿入する前に、結果の重複を排除する必要がある場合があります
    • 示されているように、ドキュメントの大きなセットは配列に対して大きすぎるため、代わりにカーソルを反復処理する必要があります
    • oplogの形式 内部と見なされ、いつでも(予告なしに)変更される可能性があるため、自己責任で使用してください


    1. MongoDB $ allElementsTrue

    2. Spring BootでCrudリポジトリを使用してRedisから結果を取得できませんか?

    3. DjangoのデータベースとしてPostgreSQLを使用しているのにRedisを使用する必要があるのはなぜですか?

    4. githubリポジトリからDockerイメージを構築する方法