Không có tùy chọn cuộn ngược (rollback has a different meaning trong ngữ cảnh MongoDB) và nghiêm túc nói rằng 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ể thực hiện được bao gồm trong các nhận xét. Tuy nhiên, với điều đó nói rằng, nếu bạn đang chạy một bộ bản sao, ngay cả một bản sao nút duy nhất được thiết lập, 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à với ví dụ. Tôi sẽ sử dụng một ví dụ đơn giản chỉ với 100 tài liệu đã bị xóa cần được khôi phục. Để vượt xa điều này (rất nhiều tài liệu, hoặc có lẽ bạn muốn chỉ khôi phục có chọn lọc, vv), bạn sẽ muốn thay đổi mã để lặp qua một con trỏ hoặc viết nó bằng ngôn ngữ bạn chọn ngoài vỏ MongoDB. Logic cơ bản vẫn giữ nguyên.
Trước 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 mà không có một lĩnh vực name
và 100 tài liệu với một name
lĩnh vực giống hệt nhau để họ có thể được nhầm loại bỏ sau:
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ờ, chúng ta hãy mô phỏng việc loại bỏ tình cờ của 100 name
văn bản của chúng tôi:
> db.foo.remove({ "name" : "some_x_name"})
WriteResult({ "nRemoved" : 100 })
Vì chúng tôi đang chạy trong bộ bản sao, chúng tôi vẫn có bản ghi các tài liệu này trong số oplog
(đang được chèn) và may mắn là những phần chèn chưa rơi vào cuối oplog
(oplog
là capped collection nhớ). Hãy xem liệu chúng tôi có thể tìm thấy chúng:
use local;
db.oplog.rs.find({op : "i", ns : "dropTest.foo", "o.name" : "some_x_name"}).count();
100
Đếm có vẻ chính xác, chúng tôi dường như vẫn có tài liệu của chúng tôi. Tôi biết từ kinh nghiệm rằng mảnh duy nhất của oplog
nhập chúng tôi sẽ cần ở đây là lĩnh vực o
, vì vậy chúng ta hãy thêm một chiếu chỉ trở lại đó (đầu ra snipped cho ngắn gọn, nhưng bạn sẽ có được ý tưởng):
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 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.Trước 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 ta tự nhắc nhở mình rằng chúng tôi chỉ có 100 tài liệu trong bộ sưu tập bây giờ, sau đó vòng qua 100 chèn, và cuối cùng là hợp lệ lại đếm 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à có bạn có nó, với một số hãy cẩn thận:
- này không có nghĩa là một chiến lược phục hồi sự thật, nhìn vào các bản sao lưu (MMS, khác), trì hoãn secondaries cho rằng, như đã đề cập trong các ý kiến
- Nó sẽ không được đặc biệt nhanh chóng để truy vấn các tài liệu trong số các oplog (bất kỳ truy vấn oplog là một bảng quét) trên một hệ thống bận rộn lớn.
- Các tài liệu có thể bị loại ra khỏi bất kỳ lúc nào (bạn có thể tạo bản sao của oplog để sử dụng sau này để cung cấp thêm thời gian)
- Tùy thuộc vào khối lượng công việc bạn có thể phải loại bỏ kết quả trước khi chèn lại chúng
- Bộ tài liệu lớn hơn sẽ quá lớn đối với mảng như được minh họa, vì vậy bạn sẽ cần phải lặp qua con trỏ thay vì
- Định dạng của
oplog
được coi là nội bộ và có thể thay đổi tại bất kỳ thời gian (không cần thông báo), do đó hãy tự chịu rủi ro khi sử dụng
Không phải trong trường hợp này, điều quan trọng là luôn luôn thực hiện sao lưu thường xuyên nếu bạn đang thực hiện dữ liệu có giá trị; Điều này đi cho bất kỳ cơ sở dữ liệu công nghệ – Sammaye
Sao lưu luôn luôn là một ý tưởng tốt, nhưng bạn cũng có thể chạy một bản sao với một sự chậm trễ để cung cấp cho bạn một tùy chọn để sửa lỗi trong quá khứ gần đây như thế này: http://docs.mongodb.org/manual/tutorial/configure-a-delay-replica-set-member/ –
Bạn có thể đã khôi phục lại thời gian nếu bạn sử dụng MMS. Không có cách nào khác để rollback !!!! – vmr