1. 程式人生 > >MongoDB數據庫備份與及時、定時恢復

MongoDB數據庫備份與及時、定時恢復

兩個 效果 mit 定期 無法 添加 圖片 公司 增量

一 研究背景需求

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

此外,我們現在的副本集沒有delay節點,當出現誤操作或需要恢復到指定時間點操作時,目前災備機制也不支持此操作。上線這種備份方案,心裏總是惶惶的。

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

二 原理分析

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

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

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

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

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

Mongodump --oplog參數

參數

參數說明

--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插入數據,源庫沒有集合order0531、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;還原時需重命名(step 5)。

(2)可以實現類似關系型數據庫的增量備份與增量還原

(3)oplog有一個非常重要的特性——冪等性(idempotent)。即對一個數據集合,使用oplog中記錄的操作重放時,無論被重放多少次,其結果會是一樣的。舉例來說,如果oplog中記錄的是一個插入操作,並不會因為你重放了兩次,數據庫中就得到兩條相同的記錄。

四 總結

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

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

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

MongoDB數據庫備份與及時、定時恢復