1. 程式人生 > 資料庫 >MongoDB釋放空閒空間的幾種常用方法

MongoDB釋放空閒空間的幾種常用方法

前言

當我們從MongoDB中刪除文件或集合時,MongoDB並不會將已經佔用了的磁碟空間釋放,它會一直維護已經佔用了磁碟空間的資料檔案,儘管資料檔案中可能存在大大小小的空記錄列表(empty record list)。當客戶端程式再次插入文件時,MongoDB會從空記錄列表中分配儲存空間給新文件。那麼為了更加有效的使用磁碟空間,我們需要對mongodb的資料檔案做碎片整理以及未使用空間的回收。思想無非兩種:

1、對原資料進行重組

2、僅將資料複製出來,形成僅資料的完整備份

以下介紹幾種常用的實施方法:

1、compact

2、db.repairDatabase()

3、secondary節點重同步

4、db.copyDatabase()

一、compat

官網對該命令的定義:對集合中的所有資料和索引進行重寫和碎片整理。

使用方法

use yourdatabase;
db.runCommand({ compact : 'yourCollection' });

注意事項

1、在執行命令前請保證你有比較新的備份

2、在使用MMAPv1儲存引擎的MongoDB上compact需要資料檔案所在分割槽至少有2G的空閒空間

3、在使用WiredTiger儲存引擎的MongoDB上,compact命令將重寫集合和索引,且釋放未使用的空間,但使用MMAPv1儲存引擎的MongoDB上,該命令只對集合的資料檔案進行碎片整理並重新建立其索引。不會釋放空間,在使用MMAPv1儲存引擎的MongoDB上回收空間,建議使用第三種方法“secondary節點重同步”

4、使用MMAPv1儲存引擎的MongoDB中的Capped Collections,是無法被壓縮的,但使用WiredTiger儲存引擎的MongoDB在執行compact時會進行壓縮。

5、在副本集上執行該命令時,要分別在每個節點執行

6、該命令只能在mongod例項上執行,不能再mongos例項上執行。也就是說針對分片叢集的compact操作要分別在每個分片節點上執行。

7、一般該命令執行在secondary節點上,在執行時,會強制節點進入RECOVERING狀態,RECOVERING狀態的例項讀寫操作將被阻塞

8、再碰到特殊情況要停止執行該命令時,可通過db.currentOp()查詢程序資訊,然後通過db.killOp()幹掉程序

9、compact可能會增加資料檔案的總大小和數量,尤其是第一次執行時。但這不會增加總集合使用的磁碟空間,因為儲存大小是資料庫檔案中分配的資料量,而不是檔案系統上檔案的大小/數量

10、使用MMAPv1儲存引擎的MongoDB中的Capped Collections,是無法被壓縮的,但使用WiredTiger儲存引擎的MongoDB在執行compact時會進行壓縮。

二、db.repairDatabase()

官網該命令的定義:通過丟無效或損壞的資料老重建資料庫和索引。類似於檔案系統修復命令fsck。所以此命令主要是用於修復資料。

使用方法

use yourdatabase;
db.repairDatabase();

注意事項

1、db.repairDatabase()主要用於修復資料。若你擁有資料的完整副本,且有許可權訪問,請使用第三種方法“secondary節點重同步”

2、在執行命令前請保證你有比較新的備份

3、此命令會完全阻塞資料庫的讀寫,謹慎操作

4、此命令執行需要資料檔案所在位置有等同於所有資料檔案大小總和的空閒空間再加上2G

5、在使用MMAPv1儲存引擎的secondary節點上執行該命令可以壓縮集合資料

6、在使用WiredTiger儲存引擎的MongoDB庫上執行不會有壓縮的效果

7、再碰到特殊情況要停止執行該命令時,可通過db.currentOp()查詢程序資訊,然後通過db.killOp()幹掉程序

8、非常消耗時間

三、secondary節點重同步

主要思想就是:刪除secondary節點中指定資料,使之與primary重新開始資料同步。當副本整合員資料太過陳舊,也可以使用重新同步。資料的重新同步與直接複製資料檔案不同,MongoDB會只同步資料,因此重同步完成後的資料檔案是沒有空集合的,以此實現了磁碟空間的回收。

使用方法

首先必須確保資料有完整的備份。

1、若是primary節點,先強制將之變為secondary節點,否則跳過此步驟:

 rs.stepdown(120);

2、然後在primary上刪除secondary節點:

 rs.remove("IP:port");

3、刪除secondary節點dbpath下的所有檔案。

4、將節點重新加入叢集,然後使之自動進行資料的同步:

 rs.add("IP:port");

5、等資料同步完成後,迴圈1-4的步驟可以將叢集中所有節點的磁碟空間釋放

針對一些特殊情況,不能下線secondary節點的,可以新增一個節點到副本集中,然後secondary就自動開始資料的同步了。

總的來說,重同步的方法是比較好的,第一基本不會阻塞副本集的讀寫,第二消耗的時間相對前兩種比較短

四、db.copyDatabase()

mongodb還支援線上複製資料:db.copyDatabase("from","to","IP:port"),此種方法也能釋放空間,因為db.copyDatabase複製的資料,而不是表示在磁碟中的資料檔案。但,該命令在4.0版本起被棄用;3.x版本還能繼續使用

如:

 db.copyDatabase("sourceDB","DistDB");

將源庫sourceDB。拷貝為DistDB。

當然,該命令支援遠端複製。

該命令的完整語法為:

db.copyDatabase(<源資料庫名稱>,<目標資料庫名稱>,<源mongodb的IP:port>,<源資料庫連線需要的賬戶>,<密碼>,<mechanism>)

以上:命令必須在目標資料庫伺服器上執行。若源資料庫與目標資料庫存在於一個MongoDB伺服器,<源mongodb的IP:port>,<密碼>都可省略。<mechanism>是身份驗證型別,可選的。

注意事項

1、db.copyDatabase()不會阻塞源資料庫和目標資料庫資料的讀寫,因此可能會出現兩份資料不一致的情況

2、db.copyDatabase()複製索引資料會鎖定資料庫,此操作也會對其他資料庫產生影響

3、db.copyDatabase()不要在mongos例項中使用

4、db.copyDatabase()不要用於複製包含分片集合的資料庫

5、在4.0版中更改:db.copyDatabase()僅支援SCRAM進行身份驗證fromhost,<mechanism>選項。

6、某些不同版本的MongoDB間不支援此種複製方法,詳見連結:https://docs.mongodb.com/manual/reference/method/db.copyDatabase/

除此之外,還有一些方法,像使用匯入/匯出的方法(mongodump/mongorestore),這種方法在資料量非常大的情況是不適用的,因為匯入匯出的方法使用的全量的形式,要保證有足夠的空閒空間來存放匯入的資料。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。