MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Czy istnieje sposób na odzyskanie ostatnio usuniętych dokumentów w MongoDB?

Nie ma opcji wycofania (cofanie ma inne znaczenie w kontekście MongoDB) i ściśle mówiąc, nie ma obsługiwanego sposobu na odzyskanie tych dokumentów - środki ostrożności, które możesz/należy podjąć, są opisane w komentarzach. Mając to na uwadze, jeśli używasz zestawu replik, nawet zestawu replik z jednym węzłem, masz oplog . Z oplog który obejmuje czas włożenia dokumentów, możesz je odzyskać.

Najłatwiej to zilustrować przykładem. Posłużę się uproszczonym przykładem z zaledwie 100 usuniętymi dokumentami, które należy przywrócić. Aby wyjść poza to (ogromna liczba dokumentów, a może chcesz tylko selektywnie przywracać itp.), będziesz chciał zmienić kod, aby iterować po kursorze lub napisać to w wybranym języku poza powłoką MongoDB. Podstawowa logika pozostaje taka sama.

Najpierw utwórzmy naszą przykładową kolekcję foo w bazie danych dropTest . Wstawimy 100 dokumentów bez name pole i 100 dokumentów z identyczną name pole, aby można je było później omyłkowo usunąć:

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

Teraz zasymulujmy przypadkowe usunięcie naszych 100 name dokumenty:

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

Ponieważ działamy w zestawie replik, nadal mamy zapis tych dokumentów w oplog (jest wstawiane) i na szczęście te wstawki nie spadły (jeszcze) z końca oplog (oplog to kolekcja ograniczona, pamiętaj) . Zobaczmy, czy uda nam się je znaleźć:

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

Liczenie wygląda poprawnie, wydaje się, że nadal mamy nasze dokumenty. Z doświadczenia wiem, że jedyny fragment oplog będziemy tu potrzebować wpisu o pole, więc dodajmy projekcję, która tylko to zwróci (wyjście obcięte dla zwięzłości, ale masz pomysł):

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

Aby ponownie wstawić te dokumenty, możemy po prostu przechowywać je w tablicy, a następnie iterować po tablicy i wstawiać odpowiednie fragmenty. Najpierw utwórzmy naszą tablicę:

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

Następnie przypominamy sobie, że mamy teraz w kolekcji tylko 100 dokumentów, potem wykonujemy pętlę nad 100 wstawkami, a na koniec ponownie sprawdzamy nasze obliczenia:

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

I masz to, z pewnymi zastrzeżeniami:

  • To nie ma być prawdziwa strategia przywracania, spójrz na kopie zapasowe (MMS, inne), opóźnione wtórne, jak wspomniano w komentarzach
  • Nie będzie szczególnie szybkie wyszukiwanie dokumentów z oploga (każde zapytanie oploga to skanowanie tabeli) w dużym, obciążonym systemie.
  • Dokumenty mogą w dowolnym momencie przestać działać w oplogu (oczywiście możesz zrobić kopię oploga do późniejszego wykorzystania, aby dać ci więcej czasu)
  • W zależności od obciążenia pracą może być konieczne usunięcie duplikatów wyników przed ich ponownym wstawieniem
  • Większe zestawy dokumentów będą zbyt duże dla tablicy, jak pokazano, więc zamiast tego będziesz musiał iterować po kursorze
  • Format oplog jest uważany za wewnętrzny i może ulec zmianie w dowolnym momencie (bez powiadomienia), więc używaj go na własne ryzyko


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak mogę jednocześnie zapisać wiele dokumentów w Mongoose/Node.js?

  2. Wybierz dokumenty, w których wszystkie wartości w polu tablicy istnieją w innej tablicy

  3. MongoDB Find wydajność:pojedynczy indeks złożony VS dwa indeksy pojedynczego pola

  4. Zapytanie agregujące MongoDB przy użyciu sterownika PHP

  5. MongoDB-as-a-Service na własnym koncie Amazon AWS