因資料插入、更新等操作長時間累積或者刪除資料會導致產生磁碟片段,本文介紹如何使用compact
命令回收磁碟片段,從而提升磁碟利用率。該命令適用於回收Primary和Secondary節點的磁碟片段。
建議使用空間分析功能回收磁碟片段,控制台操作更簡單且業務影響較小。空間分析僅回收Hidden節點的片段。回收Primary節點和Secondary節點的片段,需先進行主備切換。具體操作,請參見空間分析。
前提條件
執行個體的儲存引擎為WiredTiger。
背景資訊
在刪除ApsaraDB for MongoDB執行個體的資料後,這些被刪除資料使用的儲存空間會被標記為空白閑,隨後寫入的新資料可能會被直接儲存到這部分閒置儲存空間中,也可能會先擴充檔案的儲存空間再儲存到檔案末尾。上述情況將導致一部分閒置儲存空間不會被使用,這些未被使用的空閑儲存空間被稱之為磁碟片段,磁碟片段越多,磁碟利用率就越低。
您可以執行
db.runCommand({collStats: <collection_name>})
命令訪問節點,查看指定集合的儲存空間狀況。部分關鍵字介紹如下:size
:表示集合的邏輯儲存大小。storageSize
:表示集合的實體儲存體大小。freeStorageSize
:表示磁碟片段中空閑並可以被回收的磁碟空間,ApsaraDB for MongoDB 4.4及以上版本支援查看。
在執行
remove
命令刪除文檔後,size
的值會減少,但是storageSize
的值不一定會減少。可觀察freeStorageSize
在storageSize
中的佔比,佔比率較高時,代表磁碟片段率較高。
關於size
、storageSize
和freeStorageSize
關鍵字的更多資訊,請參見collStats-Output。
compact
在ApsaraDB for MongoDB中是一個進行空間整理與回收的命令。關於compact
命令的更多資訊,請參見compact。
注意事項
資料備份:回收磁碟片段前,建議對資料庫資料進行備份,備份方法,請參見手動備份MongoDB資料。
compact
命令影響:讀寫阻塞與效能影響
MongoDB 4.4之前的版本執行
compact
命令會導致集合所屬的資料庫被鎖定,且該資料庫的讀寫操作將被阻塞。建議您在業務低峰期操作,或者將版本升級至MongoDB 4.4及之後再進行片段回收操作。關於版本升級,請參見升級資料庫大版本。受阻塞的具體介紹,請參見MongoDB官網文檔。MongoDB 4.4及之後的版本
compact
命令不再阻塞業務讀寫,但執行過程中可能會影響效能,建議您在業務低峰期操作。
節點重搭
MongoDB 3.4全版本、MongoDB 4.0全版本、MongoDB 4.2的早期小版本(小於等於4.0.22版本)、MongoDB 4.4的早期小版本(小於等於5.0.6版本)執行個體,正在執行
compact
命令的節點會進入RECOVERING狀態,如果期間過長,該節點會被執行個體探活組件認定為節點不健康從而觸發相應的重搭操作。詳細資料,請參見MongoDB官方文檔。關於MongoDB版本的更多資訊,請參見MongoDB小版本說明。上述版本之後的MongoDB執行個體,執行
compact
命令的節點則會維持在SECONDARY狀態,不會觸發重搭操作。
compact
命令無效:以下情境可能會導致
compact
命令執行無效,更多介紹請參見開原始碼。物理集合大小小於1 MB。
檔案前80%的儲存空間中,空閑儲存空間小於20%;檔案前90%的儲存空間中,空閑儲存空間小於10%。
回收時間:執行
compact
命令回收磁碟片段所需的時間與集合資料量、系統負載等因素有關。其他:
執行
compact
命令時,可能會出現釋放的儲存空間小於閒置儲存空間的情況。如果出現上述情況,請確保前一個compact
命令執行完畢後再發起下一個,避免頻繁重複執行。compact
命令可以在磁碟空間滿導致執行個體鎖定的情況下執行。
預估回收的磁碟片段空間
通過MongoDB Shell串連ApsaraDB for MongoDB執行個體。關於複本集執行個體,為降低業務影響,建議您串連複本集執行個體的Secondary節點操作。不同類型執行個體的串連方法如下:
將資料庫切換至集合所在的資料庫。
文法:
use <database_name>
參數說明:
<database_name>
為集合所在的資料庫名稱。說明您可以通過
show dbs
命令查詢現有的資料庫。樣本:
切換至test_database資料庫。
use test_database
查看集合需回收的磁碟片段空間。
文法:
db.<collection_name>.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
參數說明:
<collection_name>
為集合名稱。說明您可以通過
show tables
命令查詢現有的集合。樣本:
db.test_database_collection.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
返回結果如下:
207806464
該返回結果表示預估回收的磁碟片段空間為207806464 Byte。
回收單節點或複本集執行個體的磁碟片段
單節點執行個體只有一個StandAlone節點,您只需要串連主節點(Primary節點),執行
compact
命令回收主節點(Primary節點)的磁碟片段。複本集執行個體具有多個節點,主節點(Primary節點)和從節點(Secondary節點)均需進行回收操作。為降低業務影響,建議您優先回收Secondary節點的磁碟片段,然後進行主備切換,將Primary節點切換到Secondary節點,再回收新Secondary節點的磁碟片段。主備切換的具體操作,請參考複本集執行個體設定主備切換。
說明如果複本集執行個體具有隻讀節點(ReadOnly節點),您還需要回收唯讀節點(ReadOnly節點)的磁碟片段,執行的回收命令與回收主從節點磁碟片段的命令相同。
通過Mongo Shell串連單節點或複本集執行個體。不同類型執行個體的串連方法如下:
將資料庫切換至集合所在的資料庫。
文法:
use <database_name>
參數說明:
<database_name>
為集合所在的資料庫名稱。說明您可以通過
show dbs
命令查詢現有的資料庫。樣本:
切換至replica_database資料庫。
use replica_database
查看回收磁碟片段前資料庫佔用的磁碟空間。
db.stats()
說明該命令可以直接複製執行,無需修改。
回收集合的磁碟片段。
文法:
db.runCommand({compact:"<collection_name>",force:true})
參數說明:
<collection_name>
:集合名稱。說明您可以通過
show tables
命令查詢現有的集合。force
:可選項,取值固定為true。如果您在4.2及以下版本的ApsaraDB for MongoDB執行個體主節點(Primary節點)上執行該命令,該參數為必填項。
樣本:
db.runCommand({compact:"sharded_collection"})
執行成功的返回結果如下:
{ "ok" : 1 }
查看回收磁碟片段後資料庫佔用的磁碟空間。
db.stats()
說明該命令可以直接複製執行,無需修改。
回收分區叢集執行個體的磁碟片段
分區叢集執行個體只需要回收Shard組件中對應節點的磁碟片段。Mongos組件和ConfigServer組件均不儲存使用者資料,並且增加和更新操作偏多,刪除操作偏少,因此不需要回收磁碟片段。
分區叢集執行個體的唯讀節點不支援compact
命令,所以無法回收唯讀節點(ReadOnly節點)的磁碟片段。
通過Mongo Shell串連分區叢集執行個體,如何串連,請參見通過Mongo Shell串連MongoDB分區叢集執行個體。
將資料庫切換至集合所在的資料庫。
文法:
use <database_name>
參數說明:
<database_name>
為集合所在的資料庫名稱。說明您可以通過
show dbs
命令查詢現有的資料庫。樣本:
切換至sharded_database資料庫。
use sharded_database
查看回收磁碟片段前資料庫佔用的磁碟空間。
db.stats()
說明該命令可以直接複製執行,無需修改。
回收集合的磁碟片段。
Shard組件中主節點(Primary節點)和從節點(Secondary節點)均需進行回收操作。為降低業務影響,建議您優先回收Secondary節點的磁碟片段,然後進行主備切換,將Primary節點切換到Secondary節點,再回收新Secondary節點的磁碟片段。主備切換的具體操作,請參考分區叢集執行個體設定主備切換。
回收Shard組件中主節點(Primary節點)的磁碟片段。
文法:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>",force:true}})
參數說明:
<Shard ID>
:Shard組件的ID。說明您可以登入MongoDB管理主控台,在目標執行個體基本資料頁面的Shard列表地區查看Shard組件的ID。
<collection_name>
:集合名稱。說明您可以通過
show tables
命令查詢現有的集合。force
:可選項,取值固定為true。如果您的分區叢集執行個體版本為4.2及以下版本,該參數為必填項。
樣本:
db.runCommand({runCommandOnShard:"shard01","command":{compact:"sharded_collection",force:true}})
回收Shard組件中從節點(Secondary節點)的磁碟片段。
本操作在mongo shell和mongosh中執行存在一定差異,請根據您使用的用戶端來選擇對應的操作方法。
mongo shell
文法:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"},$queryOptions: {$readPreference: {mode: 'secondary'}}})
參數說明:
<Shard ID>
:Shard組件的ID。說明您可以登入MongoDB管理主控台,在目標執行個體基本資料頁面的Shard列表地區查看Shard組件的ID。
<collection_name>
:集合名稱。說明您可以通過
show tables
命令查詢現有的集合。
樣本:
db.runCommand({runCommandOnShard:"shard01","command":{compact:"sharded_collection"},$queryOptions: {$readPreference: {mode: 'secondary'}}})
mongosh
說明由於mongosh v2.x版本暫不支援執行runCommandOnShard命令,在執行本操作時請您使用mongosh v1.x版本。
文法:
db.getMongo().setReadPref('secondary') db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}})
參數說明:
<Shard ID>
:Shard組件的ID。說明您可以登入MongoDB管理主控台,在目標執行個體基本資料頁面的Shard列表地區查看Shard組件的ID。
<collection_name>
:集合名稱。說明您可以通過
show tables
命令查詢現有的集合。
樣本:
db.getMongo().setReadPref('secondary') db.runCommand({runCommandOnShard:"d-2ze91ae9d55d6604","command":{compact:"test"}})
查看回收磁碟片段後資料庫佔用的磁碟空間。
db.stats()
說明該命令可以直接複製執行,無需修改。