sql >> Databáze >  >> NoSQL >> MongoDB

Existuje nějaký způsob, jak obnovit nedávno smazané dokumenty v MongoDB?

Neexistuje žádná možnost vrácení zpět (vrácení zpět má jiný význam v kontextu MongoDB) a přísně vzato neexistuje žádný podporovaný způsob, jak tyto dokumenty získat zpět - opatření, která můžete/měli byste přijmout, jsou uvedena v komentářích. Nicméně, pokud používáte sadu replik, dokonce i sadu replik jednoho uzlu, máte oplog . S oplog který pokrývá dobu, kdy byly dokumenty vloženy, je možné, že je budete moci obnovit.

Nejjednodušší způsob, jak to ilustrovat, je na příkladu. Použiji zjednodušený příklad s pouhými 100 smazanými dokumenty, které je třeba obnovit. Chcete-li překročit toto (velké množství dokumentů nebo možná chcete pouze selektivně obnovit atd.), budete chtít buď změnit kód tak, aby se opakoval přes kurzor, nebo to napsat pomocí vašeho zvoleného jazyka mimo prostředí MongoDB. Základní logika zůstává stejná.

Nejprve vytvořte naši ukázkovou kolekci foo v databázi dropTest . Vložíme 100 dokumentů bez name pole a 100 dokumentů se shodným name pole, aby mohly být později omylem odstraněny:

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"})};

Nyní simulujme náhodné odstranění našich 100 name dokumenty:

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

Protože běžíme v sadě replik, stále máme záznam o těchto dokumentech v oplog (vkládají se) a naštěstí tyto vložky (zatím) nespadly z konce oplog (oplog je omezená sbírka pamatovat) . Uvidíme, jestli je najdeme:

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

Počet vypadá správně, zdá se, že máme stále naše doklady. Ze zkušenosti vím, že jediný kousek oplog záznam, který zde budeme potřebovat, je o pole, takže přidáme projekci, která vrátí pouze toto (výstup byl kvůli stručnosti odstřižen, ale máte představu):

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" } }

Chcete-li tyto dokumenty znovu vložit, stačí je uložit do pole, poté polem iterovat a vložit příslušné kusy. Nejprve si vytvořte pole:

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

Dále si připomeneme, že nyní máme ve sbírce pouze 100 dokumentů, pak přejdeme přes 100 vložek a nakonec znovu ověříme naše počty:

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

A tady to máte, s určitými výhradami:

  • Toto není myšleno jako skutečná strategie obnovy, podívejte se na zálohy (MMS, jiné), zpožděné sekundární položky, jak je uvedeno v komentářích
  • Dotazování dokumentů z oplogu (každý dotaz oplogu je skenování tabulky) na velkém vytíženém systému nebude nijak zvlášť rychlé.
  • Dokumenty mohou z oplogu kdykoli zestárnout (můžete si samozřejmě vytvořit kopii oplogu pro pozdější použití, abyste měli více času)
  • V závislosti na pracovním vytížení možná budete muset výsledky před opětovným vložením deduplikovat
  • Větší sady dokumentů budou pro pole příliš velké, jak bylo ukázáno, takže místo toho budete muset iterovat kurzor
  • Formát oplog je považován za interní a může se kdykoli změnit (bez upozornění), takže jej používáte na vlastní riziko


  1. Redis - Seřazená sada, vyhledejte položku podle hodnoty vlastnosti

  2. MongoDB Embedded Objects nemají žádné ID (hodnota null)

  3. proč je Redis jednovláknový (řízený událostmi)

  4. Architektonické vzory pro zpracování dat téměř v reálném čase pomocí Apache Hadoop