MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Có cách nào để khôi phục các tài liệu đã xóa gần đây trong MongoDB không?

Không có tùy chọn khôi phục (khôi phục có nghĩa khác trong ngữ cảnh MongoDB) và nói đúng ra là không có cách nào được hỗ trợ để lấy lại các tài liệu này - các biện pháp phòng ngừa bạn có thể / nên thực hiện được đề cập trong các nhận xét. Tuy nhiên, với điều đó đã nói, nếu bạn đang chạy một tập hợp bản sao, thậm chí một tập hợp bản sao nút duy nhất, thì bạn có một oplog . Với oplog bao gồm khi tài liệu được chèn vào, bạn có thể khôi phục chúng.

Cách dễ nhất để minh họa điều này là bằng một ví dụ. Tôi sẽ sử dụng một ví dụ đơn giản chỉ với 100 tài liệu đã xóa cần được khôi phục. Để vượt ra ngoài điều này (số lượng lớn tài liệu hoặc có lẽ bạn chỉ muốn khôi phục một cách có chọn lọc, v.v.), bạn sẽ muốn thay đổi mã để lặp qua con trỏ hoặc viết mã này bằng ngôn ngữ bạn chọn bên ngoài MongoDB shell. Logic cơ bản vẫn như cũ.

Đầu tiên, hãy tạo bộ sưu tập mẫu của chúng tôi foo trong cơ sở dữ liệu dropTest . Chúng tôi sẽ chèn 100 tài liệu không có name trường và 100 tài liệu có name giống hệt nhau để chúng có thể bị xóa nhầm sau này:

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

Bây giờ, hãy mô phỏng việc vô tình xóa 100 name của chúng tôi tài liệu:

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

Bởi vì chúng tôi đang chạy trong một tập hợp bản sao, chúng tôi vẫn có bản ghi của những tài liệu này trong oplog (đang được chèn) và rất may là những phần chèn đó chưa (chưa) rơi ra khỏi phần cuối của oplog (oplog là một bộ sưu tập có giới hạn nhớ). Hãy xem liệu chúng ta có thể tìm thấy chúng không:

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

Số lượng có vẻ chính xác, chúng tôi dường như vẫn còn tài liệu của mình. Tôi biết từ kinh nghiệm rằng phần duy nhất của oplog mục nhập chúng ta sẽ cần ở đây là o , vì vậy hãy thêm một phép chiếu để chỉ trả về trường đó (đầu ra được cắt ngắn cho ngắn gọn, nhưng bạn hiểu rõ):

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

Để chèn lại các tài liệu đó, chúng ta chỉ có thể lưu trữ chúng trong một mảng, sau đó lặp qua mảng và chèn các phần có liên quan. Đầu tiên, hãy tạo mảng của chúng tôi:

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

Tiếp theo, chúng tôi tự nhắc mình rằng hiện tại chúng tôi chỉ có 100 tài liệu trong bộ sưu tập, sau đó lặp lại 100 tài liệu chèn và cuối cùng xác thực lại số lượng của chúng tôi:

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

Và bạn đã có nó, với một số lưu ý:

  • Đây không phải là một chiến lược khôi phục thực sự, hãy nhìn vào các bản sao lưu (MMS, khác), các bản sao thứ hai bị trì hoãn cho điều đó, như đã đề cập trong các nhận xét
  • Sẽ không đặc biệt nhanh chóng khi truy vấn các tài liệu ngoài oplog (mọi truy vấn oplog đều là quét bảng) trên một hệ thống bận lớn.
  • Các tài liệu có thể hết thời hạn sử dụng bất kỳ lúc nào (tất nhiên, bạn có thể tạo một bản sao của oplog để sử dụng sau nhằm giúp bạn có thêm thời gian)
  • Tùy thuộc vào khối lượng công việc của mình, bạn có thể phải xóa mờ các kết quả trước khi chèn lại chúng
  • Các tập hợp tài liệu lớn hơn sẽ quá lớn đối với một mảng như đã trình bày, vì vậy bạn sẽ cần phải lặp qua con trỏ để thay thế
  • Định dạng của oplog được coi là nội bộ và có thể thay đổi bất kỳ lúc nào (không cần thông báo), vì vậy bạn tự chịu rủi ro khi sử dụng


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongodb tổng hợp (đếm) trên nhiều trường đồng thời

  2. MongoDB:cập nhật mọi tài liệu trên một trường

  3. Xóa đối tượng khỏi mảng lồng nhau theo nhiều tiêu chí

  4. Tổng hợp MongoDB với $ lookup chỉ bao gồm (hoặc dự án) một số trường để trả về từ truy vấn

  5. Tìm kiếm không phân biệt chữ hoa chữ thường trong Mongo