mongodb指南(七) - developer zone - 數據庫之命令(二)

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以前,這個命令會請求解鎖並立即返回。這樣就很難知道數據庫實際上是否已經解鎖。

現在的這個命令會阻塞知道數據庫被解鎖。當它返回時,你就可以確定數據庫已經將數據文件同步到磁盤並準備好接收寫入了。


發佈了5 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章