您好,登錄后才能下訂單哦!
MongoDB如何備份以及導出導入數據,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
周二有同學問,MONGODB怎么備份,怎么數據遷移,正好最近要做一個項目的數據遷移,其中就有MONGODB ,正好以一個項目的觀念來看看MongoDb的數據遷移和備份的觀點,如果有遺漏或三觀不正,還是請大家來指正。
做這個事情,其實要先有一個測試環節,或者生產環境,這里就以兩個單機的MOGNODB4.0 來進行操作。本身MONGODB 是支持兩種數據的遷出和導入的方式,當然后面也會有兩個復制集合之間的數據遷移的東西。
一般小型系統使用mongodump 和 mongorestore 來進行系統的備份和恢復mongodump可以用來轉儲整個數據庫、集合或查詢結果。mongodump可以通過轉儲oplog來生成一致的數據快照。mongorestore實用程序將數據恢復到新的或現有的數據庫。mongorestore將從mongodump生成的BSON數據庫轉儲中導入內容,并重播oplog。
mongodump只捕獲數據庫中的文檔。產生的備份是空間有效的,但是mongorestore或mongod必須在恢復數據后重建索引。
但實際上,很多線上的MONGODB 系統可能并不是這樣備份和恢復的。
但我們還是先看看相關的命令,對于小型的系統來說還是使用這樣的方式來備份。
備份(J 為操作使用的線程, --gzip 是壓縮)
mongodump --host=192.168.198.180 --port=27027 --username=admin --password=1234.com --authenticationDatabase=admin --gzip --db test -v -j 8 -o /mongodata/backup
數據的恢復
mongorestore --host=192.168.198.181 --port=27027 --username=admin --password=1234.com --authenticationDatabase=admin --db test -v --drop -j 8 --gzip --dir='/mongodata/backup/test'
對于單機來說上面的備份和恢復的方式基本上就滿足了。當然可以寫一個腳本,然后在rsync 到對應的備份存儲的地方就可以。
但實際上很多MONGODB 的使用的方式都是復制集,那具體的復制replica set 是怎么備份的。
mongodump --uri="mongodb://backup:1234.com@10.5.1.114:27027,10.5.1.115:27027,10.5.1.116:27027/DB_AAP_LOG?replicaSet=repl&readPreference=secondary" --gzip -v -j 8 -o /wu
上面的命令就是從MONGODB3.46引入了 uri的方式連接MONGODB ,通過這樣的方式來針對復制集合來進行備份 其中 -j 的方式對數量較多的數據進行備份。由于和--db 命令有沖突,直接可以在備份的指定的認證數據庫就是要備份的數據塊即可。(如有問題請指出)
實際上這里有一個點,就是MONGODB 是不是也需要類似傳統數據庫的鎖,來將備份的數據的一致性進行一個限制,實際上這里是有選擇的如果你選擇了 mongodb 備份的時候增加了 --oplog 則會從備份開始添加相關的oplog日志,在恢復的時候可以使用,這里我個人認為就類型與 mysqldump 里面的 --single-transaction 有類似的功效。但需要的是,要對數據庫進行FULL備份的時候才能應用,而不能對數據庫中個別的庫進行備份使用,這是理所當然的數據恢復后,是否需要對索引進行一個確認
下面的腳本可以在MONGODB 中直接運行,并獲取當前數據庫的索引信息
var collectionList = db.getCollectionNames();
for(var index in collectionList){
var collection = collectionList[index];
var cur = db.getCollection(collection).getIndexes();
if(cur.length == 1){
continue;
}
for(var index1 in cur){
var next = cur[index1];
if(next["key"]["_id"] == '1'){
continue;
}
print(
"try{ db.getCollection(\""+collection+"\").ensureIndex("+JSON.stringify(next.key)+",{background:1, unique:" + (next.unique || false) + "" + (next.expireAfterSeconds > 0 ? ", expireAfterSeconds :" + next.expireAfterSeconds : "") + " })}catch(e){print(e)}")}}
另外還有一個問題,就是如果我不備份整個MONGODB 我只備份一個庫,然后想增量怎么辦,可能就需要你的collection有相關的時間字段,然后export import 根據時間來進行,可能操作會稍微有點復雜。
例如下面的數據中,我們只想根據date 界限將一些數據導出
mongoexport -uXXX -pXXXXX --host 192.168.198.180:27027 -d test -c testData -q '{ date: { $lte: { "$date": "2020-03-30T02:23:25Z" } } }' --out /mongodata/backup/testData.json
這樣我們就導出了你需要的數據
實際上如果用備份的方式,數據是可以壓縮的比較小,但靈活性就相對差一些,導入導出數據的特點就是靈活,但占用的時間和空間會大。
mongoimport -uXXX -pXXXXX --host 192.168.198.181:27027 -d test -c testData --type json --file='/mongodata/backup/testData.json'
我們用上面的命令就將對應的數據導入
這里估計很多同學都會有疑問,mongodump mongorestore 和 mongoimport mongexport 比較后者靈活性在哪里,
舉一個例子,當數據從一個表,要進入另一個表,并且有些字段還有取舍,同時由于數據可能有重復性,也就是_id 可能有重復的可能,這時你能選擇的大概率是 mongoimport mongoexport , 通過下圖的選項你可以讓那些重復可能有沖突的數據“安安靜靜”的聽你的指揮,至少你可以有選擇,如果你使用dump resotre 那就........
在回到備份,如果你的數據庫比較大,通過這樣的方法來進行備份,那就.... 比較慢,是不是有更好的方式來對數據庫進行備份,由于MONGODB 本身不具有強事務性,所以在MONGODB 備份中會經常用到這樣一個命令,從MONGODB 3.2開始,就支持卷備份了。
就是下面這個命令了,在db.fsyncLock() 將你的MONGODB 的寫鎖住,然后就可以開始拷貝你的文件了,將你的文件都拷貝走,當然你可以LVM 等方式,具體的按你心愿,
在拷貝完畢后,在直接,鍵入db.fsyncUnlock() 解鎖,數據就可以繼續寫入了。
實際上大部分的MONOGDB的數據庫的(大容量)的備份都是這樣的方式,尤其集群的方式中將從庫鎖定,然后拷貝從庫的數據到備份位置,然后解開鎖,但需要注意的是,你在操作的過程中的時間,和不要忘記你的數據庫在被鎖定,以及報警等方方面面的問題,你都需要去處理。
實際上對于MONGODB 的備份還有一種想法,就是直接在復制集的基礎上,建立一個備份節點,我知道這樣的想法可能做傳統數據庫的DB們不是很認同,如果人家的數據要回滾怎么辦,如果數據要存檔怎么辦。當然也可以有延遲庫(使用過MYSQL的小伙伴應該對這個概念不會陌生)
說到這里還是一個我的口頭禪,任何事情都要看你的業務邏輯,如果你的MONGODB 僅僅是一個流水賬,和一些日志的話,是否對這些東西必須要進行備份,另外備份的意義在哪里,例如如果你的數據庫是 cassandra 那上百個節點的時候,怎么備份呢???? 所以不同的數據庫可能會顛覆你長久以來的一些對數據庫的操作的方法和態度,這世界變化快,follow it . (如果在生產時間備份,強烈建議全部在復制集合的從庫上進行備份)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。