mongodb 基於oplog的時間點恢復

賀子_DBA時代發表於2019-12-03
本文簡單介紹mongodb時間點恢復的過程:
1.首先建立hezi集合,並插入10000條資料;
MongoDB Enterprise liuhe_rs:PRIMARY>use liuwenhe
MongoDB Enterprise liuhe_rs:PRIMARY>for ( var i = 0; i < 100000; i++) {    db.hezi.insert({id: i}); }
MongoDB Enterprise liuhe_rs:PRIMARY> db.hezi.count();
100000
2.執行備份操作,使用引數 --oplog ,會在備份路徑下產生oplog.bson檔案
[mongod@beijing-fuli-hadoop-01 backup]$  mongodump  -h 10.9.21.179 -u liuwenhe -p
liuwenhe  --authenticationDatabase admin --oplog -o /data/mongodb/backup/
假裝置份開始時間為 A 結束時間為B
3.等備份完成後,如果此時業務又insert了資料:
MongoDB Enterprise liuhe_rs:PRIMARY> db.hezi.insert({id: 100001});
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise liuhe_rs:PRIMARY> db.hezi.count();
100001
4.在時間 C點,模擬誤刪除操作
MongoDB Enterprise liuhe_rs:PRIMARY> db.hezi.remove({})
WriteResult({ "nRemoved" : 100001 })
MongoDB Enterprise liuhe_rs:PRIMARY> db.hezi.count();
0
5.那麼怎麼來恢復這個表呢?
這種情況下,應該首先停止業務,避免由於業務量大,導致把oprlog給覆蓋了,因為如果
oprlog被覆蓋了,那麼你就無法恢復出db.hezi.insert({id: 100001})這條資料,因為這條資料
是在你備份完成後插入的資料,所以你需要立刻把oplog.rs集合給dump出來以便於進行時
間點恢復,
所以分兩種情況具體如下:
情況一:
你備份開始的時間點A  到 你誤刪除的時間點C 這段時間的oplog.rs的資料沒有被覆蓋
那麼就肯定能恢復出所有的資料!直接用你後來備份的oplog.rs替換你之前全備份的產生的
oplog.bson檔案!
情況二:(分成兩種情況)
如果你備份開始的時間點A  到 你誤刪除的時間點C 這段時間的oplog.rs的資料被覆蓋了,
那麼你就只能先恢復你的全備,然後再從oplog.rs裡面儘可能找到更多的關於這個集合的
操作,然後應用,能不能全部恢復出資料,就看運氣了,這裡又有兩種情況:
情況1:備份結束B到誤刪除C 這段時間內的oplog.rs沒有被覆蓋,那麼就可以恢復出所有的資料
情況2:備份結束B到誤刪除C 這段時間內的oplog.rs被覆蓋,那麼就只能期待關於這個集合的操作
的oplog沒有被覆蓋,這樣才能恢復出所有的資料!
怎麼去分辨到底有沒有被覆蓋呢?
首先在你備份的機器上看,可以看出oplogs的開始和結束時間,當然這不一定準確,
MongoDB Enterprise liuhe_rs:PRIMARY> rs.printReplicationInfo()
configured oplog size:   51200MB
log length start to end: 1299939secs (361.09hrs)
oplog first event time:  Sat Nov 16 2019 16:53:17 GMT+0800 (CST)
oplog last event time:   Sun Dec 01 2019 17:58:56 GMT+0800 (CST)
now:                     Sun Dec 01 2019 17:59:02 GMT+0800 (CST)
最好還是從你單獨備份集合oplog.rs的備份檔案 oplog.rs.bson中去判斷:
格式化檔案oplog.rs.bson,以便於檢視時間
[mongod@beijing-fuli-hadoop-04 local]$ bsondump oplog.rs.bson >12
看備份中的oplog的開始時間
[mongod@beijing-fuli-hadoop-04 local]$ cat 12 | head
{"ts":{"$timestamp":{"t":1575040546,"i":1}},"t":{"$numberLong":"7"},"h":{"$numberLong":"-8378285387564165709"},"v":2,"op":"n","ns":"","wall":{"$date":"2019-11-29T15:15:46.661Z"},"o":{"msg":"Reconfig set","version":26}}
看備份中的oplog的結束時間
[mongod@beijing-fuli-hadoop-04 local]$ cat 12 | tail -n 1
{"ts":{"$timestamp":{"t":1575040546,"i":1}},"t":{"$numberLong":"7"},"h":{"$numberLong":"-8378285387564165709"},"v":2,"op":"n","ns":"","wall":{"$date":"2019-11-29T15:15:46.661Z"},"o":{"msg":"Reconfig set","version":26}}
同理再去檢視全備份的產生的oplog.bson中的開始時間和結束時間!就可以判斷出有沒有被覆蓋了!
情況1:
1)dump出集合oplog.rs的資料
[mongod@beijing-fuli-hadoop-01 local]$  mongodump  -h 10.9.21.179 -u liuwenhe -p liuwenhe  --authenticationDatabase admin  -d local -c oplog.rs  -o /data/mongodb/liuwenhe/
[mongod@beijing-fuli-hadoop-01 local]$ pwd
/data/mongodb/liuwenhe/local
[mongod@beijing-fuli-hadoop-01 local]$ ll
total 60308
-rw-rw-r-- 1 mongod mongod 61751065 Nov 29 19:42 oplog.rs.bson
-rw-rw-r-- 1 mongod mongod      124 Nov 29 19:42 oplog.rs.metadata.json
2)然後找到刪除hezi集合的開始時間, 當你刪除某個集合的時候,她在oplogs中是一條一條的刪除的!這個你可以使用bsondump格式化看看!
[mongod@beijing-fuli-hadoop-01 local]$ bsondump oplog.rs.bson | grep "\"op\":\"d\"" | grep liuwenhe.hezi |head
{"ts":{"$timestamp":{"t":1575025894,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"2211936654694340159"},"v":2,"op":"d","ns":"liuwenhe.hezi","ui":{"$binary":"GG4MuSZBQpm4anq5TBp00Q==","$type":"04"},"wall":{"$date":"2019-11-29T11:11:34.499Z"},"o":{"_id":{"$oid":"5de0fb7cb54dce214bb40c7b"}}}
3)需要把 前面備份的oplog.rs.bson檔案替換全備份的檔案中的oplog.bson檔案,
這裡的oplog.rs.bson其實就是我們需要的oplog.bson。因此把它重新命名後放到合適的位置!
[mongod@beijing-fuli-hadoop-03 /data/mongodb/backup/backup]$ rm -f  oplog.bson
[mongod@beijing-fuli-hadoop-03 /data/mongodb/backup/backup]$mv  oplog.rs.bson  oplog.bson
其中oplog.rs.bson是你前面單獨備份的oplog.rs, 而oplog.bson是你全備份中帶引數 --oplog產生的檔案;
4)在另一個空閒例項上恢復出之前的全備份:
先把備份從21.114copy到21.115特定的目錄中:
scp  -r  backup/  mongod@10.9.21.115:/data/mongodb/backup/
然後進行恢復:
[mongod@beijing-fuli-hadoop-03 /data]$ mongorestore   -h 10.9.21.115 -u liuwenhe -p liuwenhe --oplogReplay --oplogLimit " 1575025894 :1" --authenticationDatabase admin  --dir /data/mongodb/backup/backup/
其中 1575025894即是$timestamp中的"t", 1即是$timestamp中的"i"。這樣配置後oplog將會
重放到這個時間點以前,即正好避開了第一條刪除語句及其後面的操作,資料庫停留在災難
前狀態
驗證確實恢復出來了:
MongoDB Enterprise > db.hezi.count()
100000
5)把恢復出來的資料在恢復到生產上去:
在21.115上備份:
mongodump  -h 10.9.21.115 -u liuwenhe -p liuwenhe -d liuwenhe -dliuwenhe -c hezi --authenticationDatabase admin -o /data/mongodb/
在21.115上直接恢復,前提網路通,如果不通的話,先把備份檔案copy到生產上。然後恢復:
[mongod@beijing-fuli-hadoop-04 li]$ mongorestore   -h 10.9.21.114 -u liuwenhe -p liuwenhe -d liuwenhe -c hehe --noIndexRestore --authenticationDatabase admin  --dir /data/mongodb/backup/li/hezi.bson
情況2中的第一種情況:
備份結束B到誤刪除C 這段時間內的oplog.rs沒有被覆蓋,那麼就可以恢復出所有的資料,具體
恢復過程如下:
1.恢復一致性全備份:
[mongod@beijing-fuli-hadoop-03 /data]$ mongorestore   -h 10.9.21.115 -u liuwenhe -p liuwenhe --oplogReplay  --authenticationDatabase admin  --dir /data/mongodb/backup/backup/
2.然後再繼續增量恢復oplog,從備份的oplog.rs檔案中找到刪除hezi這個集合的時間點,因為opglog
的冪等性,可以重複執行也不會造成資料不一致,所以沒必要在匯出oplog.rs的時候選擇增量匯出;
mongorestore   -h 10.9.21.115 -u liuwenhe -p liuwenhe --oplogReplay --oplogLimit " 1575025894 :1" --authenticationDatabase admin  --dir /data/mongodb/backup/backup/local/oplog.rs.bson
情況2中的第二種情況:
備份結束B到誤刪除C 這段時間內的oplog.rs被覆蓋,那麼就只能期待關於這個集合的操作
的oplog沒有被覆蓋,這樣才能恢復出所有的資料!坦白講這種情況下,沒法確認到底關於
這個集合的操作的oplogs有沒有被覆蓋,只能先恢復看了,過程同情況2中的第一種情況;
綜上所述
mongodb的時間點恢復的過程類似於mysql藉助binlog的過程,但是區別是
mysql需要找到具體的 gtid點,增量恢復,但是mongodb的oplog是可以多次執行,這樣就使得
mongodb 藉助oprlog的時候操作簡單些;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29654823/viewspace-2666762/,如需轉載,請註明出處,否則將追究法律責任。

相關文章