挖一挖MongoDB的備份與還原(實現指定時間點還原和增量備份還原)

一  研究背景需求

目前做者所在公司的MongoDB數據庫是天天凌晨作一次全庫完整備份,但數據庫出現故障時,只能保證恢復到全備時間點,好比,00:30 作的完整備份,而出現故障是下午18:00,那麼現有的備份機制只能夠恢復到00:30,即丟失00:30 – 18:00 的操做數據。mongodb

此外,咱們如今的副本集沒有delay節點,當出現誤操做或須要恢復到指定時間點操做時,目前災備機制也不支持此操做。上線這種備份方案,內心老是惶惶的。數據庫

而且細究mongodump機制原理,此命令在運行過程當中並不會把數據庫鎖死(或創建快照,以保證整個庫凍結在一個固定的時間點),實現數據庫完整性,而是細化到集合級別,如此,會致使數據完整性問題。 例如,集合A中存放了訂單概要信息,集合B中存放了訂單的全部明細,那麼只有一個訂單有完整的明細時纔是正確的狀態。那麼備份時,若是備份集合A處於時間點x,而備份集合B處於x以後的一個時間點y時,能夠想象A和B中的數據極有可能不對應而失去意義(部分訂單有訂單明細而沒有訂單概要信息)。服務器

二  原理分析

關係型數據庫,例如MySQL ,SQL Server 都有事務日誌(或bin log),會將數據庫的DML  DDL、DCL等操做記錄在事務文件中,能夠經過日誌備份搭建還原體系。MongoDB沒有此類機制和數據文件,難以實現。ide

但MongoDB 副本集 有經過 oplog(主要記錄在local數據庫oplog.rs集合中) 實現節點間的同步,此集合記錄了數據庫的OP操做,記錄的是整個mongod實例一段時間內的全部變動(插入/更新/刪除)操做。性能

是否能夠考慮經過oplog.rs集合的備份還原來解決以上問題(數據完整性;不能還原到指定時間點;時效性差。)。測試

值得注意的是,oplog爲replica set或者master/slave模式專用,standalone模式運行mongodb並不推薦。spa

查看mongodb備份命令Mongodump,其中有一個相關參數oplog。3d

Mongodump --oplog參數rest

參數日誌

參數說明

--oplog

Use oplog for taking a point-in-time snapshot

 

該參數的主要做用是咱們在導出庫集合數據的同時生成一個oplog.bson文件,裏面存放了開始進行dump到dump結束之間全部的op log 操做。

 

注意:--oplog選項只對全庫導出有效。

相應的 Mongorestore 中與 Oplog 相關的參數

參數

參數說明

oplogReplay

replay oplog for point-in-time restore

oplogLimit

only include oplog entries before the provided Timestamp

oplogFile

oplog file to use for replay of oplog

三 驗證測試

3.1 場景1  備份還原後,如何保證數據一致性、完整性

在Insert數據過程當中,備份數據庫,爲說明問題,數據插入跨越整個備份過程。

3.1.1 在不使用--oplog 參數下備份還原

Step 1 向數據庫ygtest041602插入數據,源庫沒有集合order053一、orderdetial

插入語句:

for(var i = 0; i < 10000; i++)

{ db.order0531.insert({a: i});};

 

 

for(i=0;i<300000;i++)

{ db.orderdetial.insert({"id":i,"name":"shenzheng","addr":"龍崗","date":new Date()}); };

 

step 2  在上述命令執行期間 執行mongodump 備份

./mongodump -h 172.177.XXX.XXX --port 端口 --authenticationDatabase admin -u 用戶名 -p 密碼 --gzip -o /data/mongodb_back/mongotestdump

Step 3 還原上述備份文件 

./mongorestore -h 172.177.XXX.XXX --port 端口  --authenticationDatabase admin -u 用戶名 -p 密碼  --gzip /data/mongodb_back/mongotestdump

Step 4 檢查源庫Insert 語句, 執行完畢(必定是mongodump完畢,再insert結束;但不強調,mongorestoreinsert的時間關係)

Step 5 待語句執行完畢後,比較 源庫和 還原庫 的數據。

源庫

還原庫

咱們看到集合orderdetial在兩個數據庫不一致,有差別。即這種備份還原 沒法保證數據一致性。

3.1.2 增長 參數--oplog 參數下備份還原

Step 1 刪除 上次測試中遺留的集合 和 備份文件

Step 2 啓動insert命令

for(var i = 0; i < 10000; i++)

{ db.order0531.insert({a: i});};

 

for(i=0;i<150000;i++)

{ db.orderdetial.insert({"id":i,"name":"shenzheng","addr":"龍崗","date":new Date()}); };

 

Step 3 執行備份命令

./mongodump -h 172.177.XXX.XXX --port 端口  --oplog --authenticationDatabase admin -u 用戶名 -p密碼  --gzip -o /data/mongodb_back/mongotestdump

從打印結果來看,有對oplog命令的輸出,查看備份文件 多了一個 oplog.bson 文件

Step 4 執行還原命令,增長參數  --oplogReplay

./mongorestore -h 172.177.XXX.XXX --port 端口  --oplogReplay --authenticationDatabase admin -u 用戶名 -p 密碼  --gzip /data/mongodb_back/mongotestdump

從執行狀況來看,此類還原命令有還原oplog

Step 5 比對數據

源庫

還原庫

 

本場景測試結論:

雖然結果數據仍不一致,但從後者的備份還原過程能夠看出,有對oplog作單獨的處理。

數據能夠保證以oplog結尾爲準,實現了多集合(表)的時間一致性(MongoDB自己特性,不保證體現數據庫的事務一致性)。

 

3.2 場景二  還原到指定時間點

 

 

使用場景3.1.2 的備份文件,測試還原到備份過程當中的某個時刻。從上次備份過程可知,開始時間爲2018-05-31T11:13:46.501+0800,結束時間爲 2018-05-31T11:14:12.961+0800

此輪測試還原點選擇在此時間段內。時間還原點的選擇,假如咱們還原到orderdetial 集合"_id" : ObjectId("5b0f6876c52291864d3485b9")的插入時的時間點。

查看此時間點對應的時間和操做序列,在源庫local中的oplog.rs 集合查詢。

(oplog.rs集合的數據意義,咱們在其餘章節介紹,在此不作贅述)

"ts" : Timestamp(1527736438, 858)

此文檔對應的 "id" : 9719.0,插入時間爲2018-05-31T11:13:58.721+0800 【正好,在mongodump的過程當中】

 

Step 1 刪除還原服務器中的還原庫(上面測試遺留的數據庫)

Step 2 執行還原命令,經過--oplogLimit 參數指定時間點,時間點爲上一步查到的Timestamp(1527736438, 858)

./mongorestore -h 172.177.XXX.XXX --port 端口  --oplogReplay --oplogLimit "1527736438:858" --authenticationDatabase admin -u 用戶名 -p 密碼  /data/mongodb_back/mongotestdump

Step 3 結果驗證

從print 出來的執行過程來看,相同的備份文件,相同的還原環境,添加--oplogLimit "1527736438:858" 參數的 replay Oplog,要小於上次不帶--oplogLimit參數的全還原。

本次還原,添加 --oplogLimit,只還原了 824 KB 的oplog

2018-05-31T16:55:21.975+0800     replaying oplog

2018-05-31T16:55:22.724+0800     oplog  85.9KB

2018-05-31T16:55:25.720+0800     oplog  575KB

2018-05-31T16:55:27.231+0800     oplog  842KB

2018-05-31T16:55:27.231+0800     done

 上次,沒有添加 --oplogLimit,默認全還原,因此還原了3.22MB oplog。

2018-05-31T11:23:33.770+0800     replaying oplog

2018-05-31T11:23:34.682+0800     oplog  146KB

2018-05-31T11:23:40.686+0800     oplog  1.10MB

2018-05-31T11:23:49.688+0800     oplog  2.61MB

2018-05-31T11:23:52.680+0800     oplog  3.11MB

2018-05-31T11:23:53.246+0800     oplog  3.22MB

2018-05-31T11:23:53.246+0800     done

這也容易理解。全還原必定大於指定時間的部分還原。

數據檢驗 :

(1)此時最大ID爲"id" : 9718.0,和參數值對應的ID值連續

(2)此過程共還原數據9719,低於全還原的63862

 

本場景測試結論:

使用參數--oplogReplay –oplogLimit 能夠將數據庫還原到指定時刻。

 

3.3 場景三 oplog.rs 集合中導出數據進行還原

在場景2 中的 oplog.bson 是咱們在mongodump 全庫時,添加參數--oplog參數後自動生成的 全庫備份,受限於性能損耗和資源限制,不能高頻率執行和長時間存儲。考慮到副本集的oplog保存在oplog.rs集合中,此輪測試驗證是否只從oplog.rs導出,就能夠保證數據連續性。即從oplog.rs導出的數據是否能夠替代mongodump過程當中產生的oplog.bson.

相似於咱們從oplog.rs集合中導出MySQL的binlog文件,也相似於SQL Server Log日誌,能夠實現增量備份與增量還原。

Step 1 在上述場景中繼續測試,咱們已經執行全庫還原,只是時間點還原到"id" : 9718.0 對應的數據。

Step 2 刪除 上次全備過程當中產生的備份文件

Step 3 爲增長試驗效果,再次在源庫插入部分數據

for(var i = 0; i < 10000; i++)

{ db.order0531.insert({a: i});};

 

for(i=0;i<200000;i++)

{ db.orderdetial.insert({"id":i,"name":"shenzheng","addr":"龍崗","date":new Date()}); };

step 4 將數據庫local中集合oplog.rs 導出(建議導出時,增長時間參數,例如一小時內的或大於某時間時刻。注意,此處的測試場景中,咱們選擇的Timestamp(1527552239,1),在咱們場景2中的Timestamp(1527736438, 858)的前面,故意時間重疊)

./mongodump -h 172.177.XXX.XXX --port 端口 --authenticationDatabase admin -u 用戶名 -p 密碼 -d local -c oplog.rs  --query '{ts:{$gte:Timestamp(1527552239,1)}}' -o /data/mongodb_back/mongotestoplog

step 5 將備份產生的文件local/oplog.rs.bson,copy至還原路徑下,並將其命名爲oplog.bson

cp ./mongotestoplog/local/oplog.rs.bson ./mongotestdump/oplog.bson

step 6 執行還原命令

./mongorestore -h 172.177.XXX.XXX --port 端口  --oplogReplay --authenticationDatabase admin -u 用戶名 –p 密碼  /data/mongodb_back/mongotestdump

step 7 數據驗證

還原庫

源庫

二者數據一致

 

本場景測試結論:

(1)dumprestor 命令,能夠接受從別處而來,除了--oplog以外,可人爲獲取的從oplog.rs中導出;還原時需重命名(step 5)。

(2)能夠實現數據庫的增量備份與增量還原。咱們能夠設置Job,每小時從集合oplog.rs中導出一份操做日誌。而後再利用這些文件中進行還原。注意此處的增量,是針對數據變化的,不是針對上次的全庫備份。此概念與關係型數據庫中的增量備份還原不一樣,其實更像關係型數據庫中的日誌備份和還原。

(3)oplog有一個很是重要的特性——冪等性(idempotent)。即對一個數據集合,使用oplog中記錄的操做重放時,不管被重放多少次,其結果會是同樣的。舉例來講,若是oplog中記錄的是一個插入操做,並不會由於你重放了兩次,數據庫中就獲得兩條相同的記錄。

四 總結 

1. MongoDB 不支持事務,沒法保證備份還原命令中的事務完整性、業務一致性(無關係數型據庫中基於事務日誌的重作還原機制)。但結合命令參數--oplog,能夠實現數據、業務的時間一致性。

2. 數據庫還原時,結合參數--oplogReplay  --oplogLimit實現指定時間點的還原。

3. 搭建副本集的MongoDB,按期導出oplog.rs,能夠實現增量備份與增量還原。

 

 

本文版權歸做者全部,未經做者贊成不得轉載,謝謝配合!!!

相關文章
相關標籤/搜索