MongoDB在不同主機間複製資料庫和集合

風靈使發表於2018-10-30

MongoDB自帶了clone一族JavaScript函式來進行資料的複製,這裡我們總結了MongoDB在不同主機間複製資料庫和集合的教程,列舉出了一些主從複製操作中常用的重要函式:

  1. db.cloneCollection()
db.cloneCollection(from, collection, query)

在不同的mongodb例項間複製資料,db.cloneCollectioncloneCollection資料庫命令的一個外在體現。

function (from, collection, query) {
 assert( isString(from) && from.length );
 assert( isString(collection) && collection.length );
 collection = this._name + "." + collection;
 query = query || {};
 return this._dbCommand( { cloneCollection:collection, from:from, query:query
} );
}

引數:

from string 包含需要複製的表的mongodb例項主機名
collection string 資料例項中需要複製的表名,該命令只可以複製遠端mongodb例項上相同資料庫名稱的表
query document 可選的選項。標準的查詢語句過濾掉不需要的文件

db.cloneCollection()不允許通過mongos來複製表,只能通過mongod例項來操作。
示例:
192.168.11.51 mongod例項mydb庫,bar集合:

{ "_id" : ObjectId("53687d9df433cf04b788c6d1"), "name" : "dog" }
{ "_id" : ObjectId("53687ff1f433cf04b788c6d2"), "name" : "cat" }
{ "_id" : ObjectId("53687ff4f433cf04b788c6d3"), "name" : "tiger" }

本地mongod例項mydb庫,複製遠端主機的bar集合中滿足查詢條件的文件:

db.cloneCollection(“192.168.11.52”, “bar”, {“name” : “tiger”})
db.bar.find();
{ “_id” : ObjectId(“53687ff4f433cf04b788c6d3”), “name” : “tiger” }

  1. db.cloneDatabase()
db.cloneDatabase("hostname")

複製遠端主機的資料庫到本地,該命令假設遠端mongodb例項中擁有與本地相同的資料庫名稱。

hostname string 包含需要複製的資料庫的mongodb例項主機名

db.cloneDatabaseclone資料庫命令的一個外在體現。

function (from) {
 assert( isString(from) && from.length );
 return this._dbCommand( { clone: from } );
}

示例:
192.168.11.51 mongod例項mydb庫,
本機mongodb例項:

use mydb
db.dropDatabase();
db.cloneDatabase("192.168.11.52");
  1. db.copyDatabase()
db.copyDatabase(fromdb, todb, fromhost, username, password)

從遠端主機複製資料庫到本地,或從本地複製資料庫到遠端主機。

db.copyDatabasecopydb資料庫命令的一個外在體現。

function (fromdb, todb, fromhost, username, password) {
 assert( isString(fromdb) && fromdb.length );
 assert( isString(todb) && todb.length );
 fromhost = fromhost || "";
 if ( username && password ) {
  var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } );

  return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb,
 todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, userna
me, password ) } );
 } else {
  return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb,
 todb:todb } );
 }
}

引數:
fromdb string 源資料庫名稱
todb string 目標資料庫名稱
fromhost string 可選項,源資料庫的主機名。如果是同一主機,忽略該選項
username string 可選項,源主機名使用者名稱
password string 可選項,源主機名使用者名稱對應密碼

屬性:
(1)db.copyDatabase()執行在目標主機的mongod例項上。
(2)db.copyDatabase()會建立目標資料庫,如果其原來不存在。
(3)db.copyDatabase()需要目標機器上有足夠的空間進行復制。
(4)db.copyDatabase()並不會產生目標資料庫的即時快照。如果在複製過程中在源或目標庫發生讀寫操作,會導致資料庫不一致。
(5)db.copyDatabase()在操作過程中並不會鎖住目標主機,所以複製過程中可能出現暫時的中斷來完成其他操作。

源資料庫(fromdb):
mongodb2.6需要在源主機和目標主機擁有以下許可權來執行copydb
(1)如果源主機資料庫不是admin,必須確保擁有以下許可權:

{ resource: { db: "mySourceDB", collection: "" }, actions: [ "find" ] }
{ resource: { db: "mySourceDB", collection: "system.js" }, actions: [ "find" ] }

如果源主機是一臺遠端主機,必須確保擁有以下許可權:

{ resource: { db: "mySourceDB", collection: "system.indexes" }, actions: [ "find" ] }
{ resource: { db: "mySourceDB", collection: "system.namespaces" }, actions: [ "find" ] }

(2)如果源主機資料庫是admin,必須確保擁有以下許可權:

{ resource: { db: "admin", collection: "" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.js" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.users" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.roles" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.version" }, actions: [ "find" ] }

如果源主機是一臺遠端主機,必須確保擁有以下許可權:

{ resource: { db: "admin", collection: "system.indexes" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.namespaces" }, actions: [ "find" ] }

(3)源資料庫在遠端主機
如果從一個擁有使用者認證的遠端主機複製資料庫,需要一個擁有恰當的許可權的使用者認證。
目標資料庫(todb):
A、如果目標主機資料庫不是admin,必須確保擁有以下許可權:

{ resource: { db: "myTargetDB", collection: "" }, actions: [ "insert", "createIndex" ] }
{ resource: { db: "myTargetDB", collection: "system.js" }, actions: [ "insert" ] }

B、如果目標主機資料庫是admin,必須確保擁有以下許可權:

resource: { db: "myTargetDB", collection: "" }, actions: [ "insert", "createIndex" ] },
{ resource: { db: "myTargetDB", collection: "system.js" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.users" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.roles" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.version" }, actions: [ "insert" ] }

示例:
192.168.11.51 mongod例項mydb庫,
複製到本地newmydb庫:

db.copyDatabase("mydb", "newmydb", "192.168.11.52");
  1. cloneCollection
    從遠端mongodb例項複製集合到當前mongodb例項。集合名稱是一致的:
{ cloneCollection: "<namespace>", from: "<hostname>", query: { <query> } }

cloneCollection擁有以下的域值:

cloneCollection string 集合的名稱空間,名稱空間包含了資料庫名和集合名的組合
from string 指定遠端主機名和可選的埠號
query document 可選的,過濾選項

示例:
192.168.11.51 mongod例項mydb庫,bar集合:

{ "_id" : ObjectId("53687d9df433cf04b788c6d1"), "name" : "dog" }
{ "_id" : ObjectId("53687ff1f433cf04b788c6d2"), "name" : "cat" }
{ "_id" : ObjectId("53687ff4f433cf04b788c6d3"), "name" : "tiger" }

本地mongod例項:

db.runCommand({cloneCollection : "mydb.bar", from : "192.168.11.52:27017", query : {"name" : "tiger"}})
use mydb
db.bar.find()
{ "_id" : ObjectId("53687ff4f433cf04b788c6d3"), "name" : "tiger" }

cloneCollectionAsCapped可以利用資料庫中存在的非cpped集合建立出一個新的capped集合,操作對原來的集合沒有副作用。
指令的語法:

{ cloneCollectionAsCapped: <existing collection>, toCollection: <capped collection>, size: <capped size> }

新集合名稱在資料庫中是獨一無二的,如果要把一個已經存在的正常集合轉變為cpped集合,可以使用convertToCapped命令,在複製過程中,cloneCollectionAsCapped指令呈現出以下行為:
mongodb會已自然順序遍歷集合中的文件。
如果size小於先前集合的尺寸,會以FIFO規則刪除早先的文件。
例項:

db.runCommand({cloneCollectionAsCapped : "bar", toCollection : "barone", size : 100})
db.barone.isCapped();

true
  1. clone
    clone命令從遠端伺服器mongodb例項複製一個資料庫到當前的mongodb例項,形式如下:
{ clone: "db1.example.net:27017" }

需要注意的幾點:
(1)clone不能去操作slave節點或副本集的非主節點。
(2)clone並不支援資料庫快照功能,如果有客戶端對資料更新過了,可能造成結果不一致。
(3)clone命令必須執行在目標節點上。
(4)clone過程中,目標主機沒有鎖定,所以複製過程中可能出現暫時的中斷來完成其他操作。

  1. copydb
    從遠端主機複製資料庫到本地,或從本地複製資料庫到遠端主機。
    在本地admin庫裡執行以下命令語法:
{ copydb: 1,
 fromhost: <hostname>,
 fromdb: <database>,
 todb: <database>,
 slaveOk: <bool>,
 username: <username>,
 nonce: <nonce>,
 key: <key> }

選項:

fromhost string 執行mongodb例項的遠端源主機,如果是本地可以忽略
fromdb string 源資料庫名稱
todb string 目標資料庫名稱
slaveOk boolean 可選的,設定為true,允許從從庫複製庫
username string 可選的,遠端主機的使用者名稱。
nonce string 可選的,遠端主機的共享金鑰
key string 可選的,遠端主機的認證密碼雜湊

屬性:
(1)copydb()執行在目標主機的mongod例項上。
(2)copydb()會建立目標資料庫,如果其原來不存在。
(3)copydb()需要目標機器上有足夠的空間進行復制。
(4)copydb()並不會產生目標資料庫的即時快照。如果在複製過程中在源或目標庫發生讀寫操作,會導致資料庫不一致。
(5)copydb()在操作過程中並不會鎖住目標主機,所以複製過程中可能出現暫時的中斷來完成其他操作。
mongodb2.6需要在源主機和目標主機擁有以下許可權來執行copydb。
(1)如果源主機資料庫不是admin,必須確保擁有以下許可權:

{ resource: { db: "mySourceDB", collection: "" }, actions: [ "find" ] }
{ resource: { db: "mySourceDB", collection: "system.js" }, actions: [ "find" ] }

如果源主機是一臺遠端主機,必須確保擁有以下許可權:

{ resource: { db: "mySourceDB", collection: "system.indexes" }, actions: [ "find" ] }
{ resource: { db: "mySourceDB", collection: "system.namespaces" }, actions: [ "find" ] }

(2)如果源主機資料庫是admin,必須確保擁有以下許可權:

{ resource: { db: "admin", collection: "" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.js" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.users" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.roles" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.version" }, actions: [ "find" ] }

如果源主機是一臺遠端主機,必須確保擁有以下許可權:

{ resource: { db: "admin", collection: "system.indexes" }, actions: [ "find" ] }
{ resource: { db: "admin", collection: "system.namespaces" }, actions: [ "find" ] }

(3)源資料庫在遠端主機
如果從一個擁有使用者認證的遠端主機複製資料庫,需要一個擁有恰當的許可權的使用者認證。
目標資料庫(todb):
A、如果目標主機資料庫不是admin,必須確保擁有以下許可權:

{ resource: { db: "myTargetDB", collection: "" }, actions: [ "insert", "createIndex" ] }
{ resource: { db: "myTargetDB", collection: "system.js" }, actions: [ "insert" ] }

B、如果目標主機資料庫是admin,必須確保擁有以下許可權:

resource: { db: "myTargetDB", collection: "" }, actions: [ "insert", "createIndex" ] },
{ resource: { db: "myTargetDB", collection: "system.js" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.users" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.roles" }, actions: [ "insert" ] },
{ resource: { db: "myTargetDB", collection: "system.version" }, actions: [ "insert" ] }

認證:
如果遠端主機需要安全認證,則需要使用username,nonce和key進行認證。
nonce是一個一次性的密碼,通過執行copydbgetnonce命令:

use admin
mynonce = db.runCommand( { copydbgetnonce : 1, fromhost: <hostname> } ).nonce

如果直接在遠端主機執行copydbgetnonce命令,可以忽略fromhost選項。
如下生成一個雜湊鍵:

hex_md5(mynonce + username + hex_md5(username + ":mongo:" + password))

副本集:設定slaveOktrue,可以在從節點執行copydb
分片集:不要在mongos例項上執行copydb;不要複製包含分片集合的庫。

例項:
(1)執行在同一主機上的copydb

(2)從遠端主機複製的copydb

db._adminCommand({
 copydb : 1,
 fromdb : "mydb",
 todb : "mydbtwo",
 formhost : "192.168.11.52"
})
{ "ok" : 1 }

(3)從需要安全驗證的遠端主機複製的copydb
遠端主機建立使用者test:caoqing/mydb

use admin
mynonce = db.runCommand( { copydbgetnonce : 1, fromhost: "192.168.11.51:27017" } ).nonce
mykey = hex_md5(mynonce + "test" + hex_md5("test" + ":mongo:" + "caoqing"))
db._adminCommand({
 copydb: 1,
 fromdb: "mydb",
 todb: "mydbthree",
 fromhost: "192.168.11.51",
 username: "test",
 nonce: mynonce,
 key: mykey
})
{ "ok" : 1 }

相關文章