compact命令
v1.9+
壓縮命令會對一個集合進行壓縮和除片段。索引也會被重建和壓縮。這會為資料庫中其他集合釋放空間。在概念上它和repairDatabase類似,但是它僅僅作用於一個集合而不是整個資料庫。
運行(mongo shell上面的樣本):
> db.runCommand( { compact : 'mycollectionname' } )
OR
> db.mycollection.runCommand( "compact" )
這個命令直到壓縮全部完成才會返回。你可以通過查看mongod記錄檔案或者在另一個shell執行個體中運行db.currentOp()來查看中間進展。
由於它會阻塞所有的活動,因此該命令預設情況下不會在複製組的主節點運行。否則它會返回錯誤。想要強制在複製組主節點上運行,使用將force:true作為參數的壓縮命令。
運行一個壓縮
與repairDatabase不同,壓縮命令不需要兩倍的硬碟空間來完成工作。它在工作的時候只需要少量額外的空間。另外,壓縮要更快一些。
儘管比repairDatabase要快一些,該命令在運行期間會阻塞所有其他動作,並且慢吞吞的。可以在安排的維護期間運行它。
如果你在複製組的輔助節點運行這個命令,輔助節點會自動把自己降級為"recovery"狀態,直到壓縮完成。
取消一個壓縮
在壓縮的開始,集合的索引會被刪除。壓縮結束時,索引會重建。因此如果在壓縮操作的中間你把它取消了,使用killOp或者伺服器失效,你的集合的索引可能會丟失。如果你使用了參數--journal運行,在壓縮過程中的宕機應該不會有資料丟失,雖然在啟動時索引可能不存在了。(儘管如此,永遠在系統維護之前像這樣做一次備份)當索引重建後,它們將會是2.0版本的索引格式。
如果在這個命令執行期間發生了宕機,只要日誌功能啟用了,你的資料將會是安全的。不過,一塊不可恢複盤區還是留下來了。唯一可以移除這塊盤區的辦法就是在整個資料庫上面執行修複操作。但是除非使用了額外空間,否則這孤立的盤區不會表現出任何問題。
另外,如果壓縮操作被中斷了,那麼這個集合中大部分空閑空間可能變得不可用。在這種情況下推薦再執行一次壓縮,完成壓縮,恢複空閑空間。
壓縮的效果
你可能會在壓縮之前和之後運行collstats命令(在shell中是db.collectionname.stats())來查看集合的儲存空間都怎麼變化了。
這個命令對集合中沒有填充因素(Padding Factor)的文檔做了充分壓縮。如果你常常執行會使文檔增大的更新操作,這會降低更新的效能因為文檔需要經常移動。
壓縮可能會將你的資料檔案的總大小增長到2GB。即使在這種情況下,集合使用的總的儲存空間還是會下降。
詳細資料
- 壓縮可能在複製組輔助節點和從節點上面執行。壓縮命令不會複製,因此每一台主機需要單獨的進行壓縮。
- 當前,壓縮是發布給mongod的命令。在一個分區環境,應該作為一個維護操作對每一個分區單獨的執行壓縮。(在將來的版本中可能會改變,和其他增強功能一起)
- 固定大小的集合是不能被壓縮的。(然而,固定大小集合中的文檔是不受片段管理的。)
複製組
- 單獨的對每一個成員壓縮。
- 理想的壓縮是運行在一個輔助節點(看上面關於force:true的評論)。
- 如果壓縮運行在輔助節點上,輔助節點會自動進入"recovering"狀態(阻止在壓縮過程中被路由來的讀操作)。一旦壓縮結束,它會自動返回到輔助狀態。
拷貝資料庫命令
mongodb包含有將一個資料庫從一台伺服器拷貝到另外一台伺服器的命令。
這些選項比可選的方法執行mongodump和mongorestore要快,因為它跳過了在磁碟上建立臨時BSON描述的步驟。
copydb命令
將一台伺服器上面一個名字的整個資料庫拷貝到另外一台伺服器並使用另外一個名字。在相同的伺服器拷貝一個資料庫到另外名稱的資料庫可以省略掉<from_hostname>.拷貝命令必鬚髮送並在目標伺服器執行。
> // shell helper syntax:
> db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>);
> // if you must authenticate with the source database
> db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>, <username>, <password>);
> // pure command syntax (runnable from any driver):
> db.runCommand(
... {copydb: 1, fromhost: <hostname>, fromdb: <db>,
... todb: <db>[, slaveOk: <bool>, username: <username>,
... nonce: <nonce>, key: <key>]}";
> // command syntax for authenticating with the source:
> n = db.runCommand( { copydbgetnonce : 1, fromhost: ... } );
db.runCommand( { copydb : 1, fromhost: ..., fromdb: ..., todb: ..., username: ..., nonce: n.nonce,
key: <hash of username, nonce, password > } );
cloneDatabase
和copydb相似,但是使用了簡單化的文法。適用於我們只不過拷貝一個資料庫到這台伺服器,並使用原來的名稱。
> db.cloneDatabase(<from_hostname>);
注釋:
- copyDatabase 可以對從節點/輔助節點運行(換句話說,原始伺服器可以是一個從節點/輔助節點)。
- copyDatabase沒有任何意義上的快照:如果在拷貝期間來源資料庫正在變化,目標資料庫會接收到不同時間點的文檔。
- 這個命令必須運行在目標伺服器。
- 這個命令在執行期間不會鎖定原始伺服器和目標伺服器。每一段都會周期性的允許其他的讀/寫操作通過。
fsync命令
fsync命令允許我們將所有掛起寫操作重新整理到資料檔案。更重要的,它還提供了鎖選項讓備份更加容易。
fsync命令強制讓資料庫重新整理所有的資料檔案:
> use admin
> db.runCommand({fsync:1});
預設情況下這個命令在同步完成後返回。需要立即返回,請使用:
> db.runCommand({fsync:1,async:true});
要定期同步,在命令列選項中使用--syncdelay命令(查看mongod --help輸出)。預設每60s做一次強制完全重新整理。
鎖,快照和解鎖
同步命令支援鎖選項,這樣就可以安全的對資料庫的資料檔案進行快照。當被鎖住後,所有的寫操作會阻塞,雖然讀操作依舊允許。快照完成後,使用解鎖命令對資料庫解鎖並允許再次上鎖。例如:
> use admin
switched to db admin
> db.runCommand({fsync:1,lock:1})
{
"info" : "now locked against writes",
"ok" : 1
}
> db.currentOp()
{
"inprog" : [
],
"fsyncLock" : 1
}
>// do some work here: for example, snapshot datafiles...
>// runProgram("/path/to/my-filesystem-snapshotting-script.sh")
> db.$cmd.sys.unlock.findOne();
{ "ok" : 1, "info" : "unlock requested" }
> // unlock is now requested. it may take a moment to take effect.
> db.currentOp()
{ "inprog" : [ ] }
附加說明
當資料庫因為快照而被鎖住時是可讀的,如果嘗試進行寫,這會阻塞讀的人因為資料庫使用了一個讀/寫鎖。這將來會被處理掉。
對從節點快照
上面的流程都是針對複製組從節點的。從節點在被鎖期間不會執行任何操作。無論如何,請看附件說明部分。
分區
同步命令只能發給一個單獨的節點,而不是整個分區叢集。
1.9的改變
mongodb1.9中引入了兩個新的shell輔助函數:db.fsyncLock()和db.fsyncUnlock().它們是出於方便的原因提供的,它們封裝了上面關於這個介面描述的功能。接下來你可以看一下它們的實現:
> db.fsyncLock
function () {
return db.adminCommand({fsync:1, lock:true});
}
> db.fsyncUnlock
function () {
return db.getSiblingDB("admin").$cmd.sys.unlock.findOne();
}
現在解鎖調用會阻塞
值得注意的是,解鎖命令做了小小的改動。在1.9.0以前,這個命令會請求解鎖並立即返回。這樣就很難知道資料庫實際上是否已經解鎖。
現在的這個命令會阻塞知道資料庫被解鎖。當它返回時,你就可以確定資料庫已經將資料檔案同步到磁碟並準備好接收寫入了。