sql >> Databasteknik >  >> NoSQL >> MongoDB

Finns det något sätt att återställa nyligen raderade dokument i MongoDB?

Det finns inget återställningsalternativ (återställning har en annan betydelse i MongoDB-sammanhang), och strängt taget finns det inget stöd för att få tillbaka dessa dokument - de försiktighetsåtgärder du kan/bör vidta tas upp i kommentarerna. Men med det sagt, om du kör en replikuppsättning, även en enskild nodreplikuppsättning, så har du en oplog . Med en oplog som täcker när dokumenten infogades, kanske du kan återställa dem.

Det enklaste sättet att illustrera detta är med ett exempel. Jag kommer att använda ett förenklat exempel med bara 100 raderade dokument som behöver återställas. För att gå utöver detta (stort antal dokument, eller kanske du bara vill återställa selektivt etc.) vill du antingen ändra koden för att iterera över en markör eller skriva detta med ditt valda språk utanför MongoDB-skalet. Den grundläggande logiken förblir densamma.

Låt oss först skapa vår exempelsamling foo i databasen dropTest . Vi kommer att infoga 100 dokument utan ett name fält och 100 dokument med ett identiskt name så att de av misstag kan tas bort senare:

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

Låt oss nu simulera oavsiktlig borttagning av vårt 100 name dokument:

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

Eftersom vi kör i en replikuppsättning har vi fortfarande ett register över dessa dokument i oplog (läggs in) och tack och lov har dessa inlägg inte (ännu) fallit utanför slutet av oplog (oplog är en begränsad samling kom ihåg). Låt oss se om vi kan hitta dem:

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

Räkningen ser korrekt ut, vi verkar ha våra dokument kvar. Jag vet av erfarenhet att den enda delen av oplog posten vi behöver här är o fältet, så låt oss lägga till en projektion för att bara returnera det (utdata klippt för korthets skull, men du fattar):

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

För att infoga dessa dokument igen kan vi bara lagra dem i en array, sedan iterera över arrayen och infoga de relevanta bitarna. Låt oss först skapa vår array:

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

Därefter påminner vi oss själva om att vi bara har 100 dokument i samlingen nu, sedan går vi över de 100 bilagorna och validerar slutligen våra räkningar:

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

Och där har du det, med några varningar:

  • Detta är inte menat att vara en riktig återställningsstrategi, titta på säkerhetskopior (MMS, annat), fördröjda sekundärer för det, som nämnts i kommentarerna
  • Det kommer inte att gå särskilt snabbt att söka efter dokumenten från oploggen (vilken som helst oplog-fråga är en tabellskanning) på ett stort upptaget system.
  • Dokumenten kan åldras ur oploggen när som helst (du kan naturligtvis göra en kopia av oploggen för senare användning för att ge dig mer tid)
  • Beroende på din arbetsbelastning kan du behöva de-dupera resultaten innan du infogar dem igen
  • Större uppsättningar dokument kommer att vara för stora för en array som visat, så du måste iterera över en markör istället
  • Formatet för oplog anses vara intern och kan ändras när som helst (utan förvarning), så använd på egen risk


  1. MongoDB count Kommando

  2. Meltdown Performance Impact on MongoDB:AWS, Azure &DigitalOcean

  3. MongoDB findOneAndDelete()

  4. 6 viktiga Redis-övervakningsstatistik du behöver titta på