MongoDB備份(mongodump)與恢復(mongorestore)工具實踐


mongodump和mongorestore實踐

1.mongodump備份工具

  • mongodump能夠在Mongodb運行時進行備份,它的工作原理是對運行的Mongodb做查詢,然后將所有查到的文檔寫入磁盤。
  • mongodump的參數與mongoexport的參數基本一致

1.1 mongodump關鍵參數如下所示:

mongodump --help查看幫助命令

  • -h,--host :代表遠程連接的數據庫地址,默認連接本地Mongo數據庫;
  • --port:代表遠程連接的數據庫的端口,默認連接的遠程端口27017;
  • -u,--username:代表連接遠程數據庫的賬號,如果設置數據庫的認證,需要指定用戶賬號;
  • -p,--password:代表連接數據庫的賬號對應的密碼;
  • -d,--db:代表連接的數據庫;
  • -c,--collection:代表連接數據庫中的集合;
  • -o, --out:代表導出的文件輸出目錄;
  • -q, --query:代表查詢條件;
  • -j,--numParallelCollections =要並行轉儲的集合數(默認為4)
  • --gzip,使用Gzip壓縮存檔;
  • --oplog,使用oplog進行時間點快照;
  • --authenticationDatabase,指定用戶鑒定庫

1.2 mongodump參數實踐

全庫備份
mongodump -u -p --port 28020 --authenticationDatabase admin -o /tmp/backup
備份指定的庫,test庫
mongodump -u -p --port 28020 --authenticationDatabase admin -d test -o /tmp/backup
備份test庫下的customer集合
mongodump -u -p --port 28020 --authenticationDatabase admin -d test -c customer -o /tmp/backup
壓縮備份
壓縮備份單庫
mongodump -u -p --port 28020 --authenticationDatabase admin -d test -o /tmp/backup --gzip

壓縮備份單表
mongodump -u -p --port 28020 --authenticationDatabase admin -d test -c customer -o /tmp/backup --gzip

2.mongorestore恢復工具

2.1 mongorestore關鍵參數如下所示:

mongodump --help查看幫助命令

  • -h,--host :代表遠程連接的數據庫地址,默認連接本地Mongo數據庫;
  • --port:代表遠程連接的數據庫的端口,默認連接的遠程端口27017;
  • -u,--username:代表連接遠程數據庫的賬號,如果設置數據庫的認證,需要指定用戶賬號;
  • -p,--password:代表連接數據庫的賬號對應的密碼;
  • -d,--db:代表連接的數據庫;
  • -c,--collection:代表連接數據庫中的集合;
  • -o, --out:代表導出的文件輸出目錄;
  • --dir = <目錄名稱>輸入目錄
  • --drop導入前刪除數據庫中集合;
  • --gzip,解壓Gzip壓縮存檔還原;
  • --oplog,重放oplog以基於時間點還原;
  • --oplogFile = <文件名>指定重播oplog的oplog文件
  • --authenticationDatabase,指定用戶鑒定庫

2.2 mongorestore參數實踐

單庫恢復
mongorestore -u -p --port 28018 --authenticationDatabase admin -d test /tmp/backup/test
恢復test庫下的customer集合
mongorestore -u -p --port 28018 --authenticationDatabase admin -d test -c customer /tmp/backup/test/customer.bson
--drop參數實踐恢復

恢復的時候,先刪除當前數據,然后恢復備份的數據。就是說,備份后添加修改的數據都會被刪除,謹慎使用!!!

# 恢復單庫
mongorestore -u -p --port 28018 --authenticationDatabase admin -d test --drop /tmp/backup/test

# 恢復單表
mongorestore -u -p --port 28018 --authenticationDatabase admin -d test -c customer --drop /tmp/backup/test/customer.bson 
--gzip參數實踐恢復
mongorestore -u -p --port 28018 --authenticationDatabase admin --gzip /tmp/backup

3.MongoDB中的oplog

3.1 什么是oplog

  • 當Primary進行寫操作的時候,會將這些寫操作記錄寫入Primary的Oplog中,而后Secondary會將Oplog 復制到本機並應用這些操作,從而實現Replication的功能。
  • 同時由於其記錄了Primary上的寫操作,故還能將其用作數據恢復。
  • 可以簡單的將其視作Mysql中的binlog。
  • oplog為replica set或者master/slave模式專用(standalone模式運行mongodb並不推薦)

3.2 oplog相關的操作

  • 在replica set中oplog是一個定容集合(capped collection),它的默認大小是磁盤空間的5%(可以通過--oplogSizeMB參數修改)
  • 其中記錄的是整個mongod實例一段時間內數據庫的所有變更(插入/更新/刪除)操作。當空間用完時新記錄自動覆蓋最老的記錄。
oplog的位置:
oplog在local庫: local.oplog

master/slave 架構下:local.oplog.$main;

replica sets 架構下:local.oplog.rs
oplog時間窗口覆蓋時間
easydb:PRIMARY> rs.printReplicationInfo()
configured oplog size:   2048MB   <--集合大小
log length start to end: 524592secs (145.72hrs)  <--預計窗口覆蓋時間
oplog first event time:  Fri Jan 08 2021 18:30:18 GMT+0800 (CST)
oplog last event time:   Thu Jan 14 2021 20:13:30 GMT+0800 (CST)
now:                     Thu Jan 14 2021 20:13:35 GMT+0800 (CST)
查看oplog內容
easydb:PRIMARY> use local
easydb:PRIMARY> db.oplog.rs.find().pretty()
{
	"ts" : Timestamp(1610101818, 1),
	"h" : NumberLong("-124421688313536398"),
	"v" : 2,
	"op" : "n",
	"ns" : "",
	"wall" : ISODate("2021-01-08T10:30:18.329Z"),
	"o" : {
		"msg" : "initiating set"
	}
}

3.3 oplog數據結構

下面來分析一下oplog中字段的含義,通過下面的命令取出一條oplog:

db.oplog.rs.find().skip(1).limit(1).toArray()

easydb:PRIMARY> use local
switched to db local
easydb:PRIMARY> db.oplog.rs.find().skip(1).limit(1).toArray()
[
	{
		"ts" : Timestamp(1610101831, 1),
		"t" : NumberLong(1),
		"h" : NumberLong("-5190685117971188188"),
		"v" : 2,
		"op" : "n",
		"ns" : "",
		"wall" : ISODate("2021-01-08T10:30:31.356Z"),
		"o" : {
			"msg" : "new primary"
		}
	}
]

  • ts: 8字節的時間戳,由4字節unix timestamp + 4字節自增計數表示。這個值很重要,在選舉(如master宕機時)新primary時,會選擇ts最大的那個secondary作為新primary
  • op:1字節的操作類型
    • "i": insert
    • "u": update
    • "d": delete
    • "c": db cmd
    • "db":聲明當前數據庫 (其中ns 被設置成為=>數據庫名稱+ '.')
    • "n": no op,即空操作,其會定期執行以確保時效性
  • ns:操作所在的namespace
  • o:操作所對應的document,即當前操作的內容(比如更新操作時要更新的的字段和值)
  • o2: 在執行更新操作時的where條件,僅限於update時才有該屬性

3.4 --oplog參數說明

mongodump --oplog參數說明
[root@mysql02 ~]# mongodump --help
--oplog     use oplog for taking a point-in-time snapshot
mongorestore --oplog參數說明
參數 參數說明
--oplogReplay 重放oplog.bson中的操作內容
--oplogLimit 與--oplogReplay一起使用時,可以限制重放到指定的時間點

3.5 mongodump使用--oplog參數備份

首先我們在mongodb中模擬一個不斷有插入操作的集合foo

use test
for(var i = 0; i < 10000; i++) {
    db.foo.insert({a: i});
}

然后在插入過程中模擬一次mongodump全備,並添加--oplog參數

[root@mysql02 ~]# mongodump -u -p --port 28018 --authenticationDatabase admin --oplog -o /tmp/backup
2021-01-14T20:51:15.254+0800	writing admin.system.version to 
2021-01-14T20:51:15.255+0800	done dumping admin.system.version (1 document)
2021-01-14T20:51:15.255+0800	writing test.foo to 
2021-01-14T20:51:15.474+0800	done dumping test.foo (1701 documents)
2021-01-14T20:51:15.483+0800	writing captured oplog to 
2021-01-14T20:51:15.509+0800		dumped 73 oplog entries


[root@mysql02 ~]# ll /tmp/backup
總用量 12
drwxr-xr-x 2 root root    69 1月  14 20:51 admin
-rw-r--r-- 1 root root 10804 1月  14 20:51 oplog.bson
drwxr-xr-x 2 root root    47 1月  14 20:51 test

從dump開始到結束的時間系統將記錄所有的oplog到oplog.bson文件中

注意:--oplog選項只對全庫導出有效,所以不能指定-d選項。

3.6 mongorestore使用--oplog參數恢復

[root@mysql02 ~]# mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay --drop /tmp/backup
2021-01-14T21:13:52.134+0800	preparing collections to restore from
2021-01-14T21:13:52.144+0800	reading metadata for test.foo from /tmp/backup/test/foo.metadata.json
2021-01-14T21:13:52.199+0800	restoring test.foo from /tmp/backup/test/foo.bson
2021-01-14T21:13:52.291+0800	no indexes to restore
2021-01-14T21:13:52.291+0800	finished restoring test.foo (1701 documents)  <--表示test.foo集合中恢復了1701個文檔
2021-01-14T21:13:52.291+0800	replaying oplog  <--表示重放了oplog中的所有操作
2021-01-14T21:13:52.407+0800	done


easydb:PRIMARY> db.foo.count()
1771  <--所以實際比1701個多,因為應用了oplog中的數據

這就是 oplog 配合 mongodump 實現熱備功能

4.利用oplog實現任意時間點數據恢復

oplog有兩種來源:

  • mongodump時加上--oplog選項,自動生成的oplog,這種方式的oplog直接 --oplogReplay 就可以恢復
  • 單獨備份獲取的oplog

例如:

mongodump  --port 28021 -d local -c oplog.rs

4.1 模擬一個持續寫入的生產環境

easydb:PRIMARY> use test
switched to db test

easydb:PRIMARY> for(i=0;i<30000;i++){ db.easydb.insert({"id":i,"name":"easydb.net","age":18,"date":new Date()}); }
WriteResult({ "nInserted" : 1 })

4.2 插入數據的同時備份

[root@mysql02 ~]# mongodump -u -p --port 28018 --authenticationDatabase admin --oplog -o /tmp/backup
2021-01-15T11:46:14.449+0800	writing admin.system.version to 
2021-01-15T11:46:14.451+0800	done dumping admin.system.version (1 document)
2021-01-15T11:46:14.452+0800	writing test.easydb to 
2021-01-15T11:46:15.799+0800	done dumping test.easydb (20154 documents)
2021-01-15T11:46:15.805+0800	writing captured oplog to 
2021-01-15T11:46:15.991+0800		dumped 1601 oplog entries

4.3 備份完成后模擬一個錯誤的操作

easydb:PRIMARY> use test
switched to db test

easydb:PRIMARY> show collections
easydb

easydb:PRIMARY> db.dropDatabase()
{
	"dropped" : "test",
	"ok" : 1,
	"operationTime" : Timestamp(1610682482, 2),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1610682482, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

4.4 切割全備里的oplog,找出上次全備最后一個時間的數據

[root@mysql02 ~]# bsondump /tmp/backup/oplog.bson > /tmp/oplog.json
2021-01-16T17:28:56.252+0800	417 objects found
[root@mysql02 ~]# tail -1 /tmp/oplog.json 
{"ts":{"$timestamp":{"t":1610789118,"i":416}},"t":{"$numberLong":"6"},"h":{"$numberLong":"8277197316656995929"},"v":2,"op":"i","ns":"test.easydb","ui":{"$binary":"JEUrQxOWS6Gw8vfPIetrqQ==","$type":"04"},"wall":{"$date":"2021-01-16T09:25:18.435Z"},"o":{"_id":{"$oid":"6002b0fe4994bdfbd2b0747e"},"id":17511.0,"name":"easydb.net","age":18.0,"date":{"$date":"2021-01-16T09:25:18.443Z"}}}

{"t":1610789118,"i":416}就是上一次全備最后的時間戳

4.5 導出上一次全備以后的增量數據

 mongodump -u -p --port 28018 --authenticationDatabase admin -d local -c oplog.rs -q '{ts:{$gt:Timestamp(1610789118,416)}}' -o /tmp/oplog
 
 #這里填的是我們上一步截取的時間戳

4.6 恢復最近一次全備的數據

mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay  /tmp/backup

easydb:PRIMARY> use test
switched to db test
easydb:PRIMARY> db.easydb.count()
17512

檢查全備恢復了多少條數據

4.7 截取備份出來增量的oplog,找到誤刪庫的時間點(limt)

  • 刪庫語句的上一個oplog時間戳為終點。
[root@mysql02 ~]# bsondump /tmp/oplog/local/oplog.rs.bson | grep -C 5 dropDatabase
{"ts":{"$timestamp":{"t":1610789163,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-8852159408511820267"},"v":2,"op":"n","ns":"","wall":{"$date":"2021-01-16T09:26:03.551Z"},"o":{"msg":"periodic noop"}}
{"ts":{"$timestamp":{"t":1610789168,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-8231808943143165392"},"v":2,"op":"c","ns":"test.$cmd","ui":{"$binary":"JEUrQxOWS6Gw8vfPIetrqQ==","$type":"04"},"wall":{"$date":"2021-01-16T09:26:08.735Z"},"o":{"drop":"easydb"}}
2021-01-16T17:51:45.426+0800	12587 objects found
{"ts":{"$timestamp":{"t":1610789168,"i":2}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-1802663680461751854"},"v":2,"op":"c","ns":"test.$cmd","wall":{"$date":"2021-01-16T09:26:08.807Z"},"o":{"dropDatabase":1}}
{"ts":{"$timestamp":{"t":1610789183,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"7216379125886047426"},"v":2,"op":"n","ns":"","wall":{"$date":"2021-01-16T09:26:23.551Z"},"o":{"msg":"periodic noop"}}
{"t":1610789168,"i":1}

將過濾出來的Unix時間戳進行轉換,再次確認是不是誤操作的時間點

4.8 復制增量的oplog到備份目錄,重命名為oplog.bson,將原來的oplog.bson覆蓋

cp /tmp/oplog/local/oplog.rs.bson /tmp/backup/oplog.bson

4.9 將增量的oplog進行恢復,添加之前找到的誤刪除的點(limt)

mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay --oplogLimit "1610789168:1"  /tmp/backup

easydb:PRIMARY> db.easydb.count()
30000
再次檢查,發現30000條數據已經全部恢復

4.10 把恢復后的數據再做一次全備,至此一次恢復就完成了

因為有悔,所以披星戴月;因為有夢,所以奮不顧身! 個人博客首發:easydb.net 微信公眾號:easydb 關注我,不走丟!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM