因資料插入、更新等操作長時間累積或者刪除資料會導致產生磁碟片段,本文介紹如何使用compact命令回收磁碟片段,從而提升磁碟利用率。該命令適用於回收Primary和Secondary節點的磁碟片段。
建議使用空間分析功能回收磁碟片段,控制台操作更簡單且業務影響較小。空間分析僅回收Hidden節點的片段,如需回收Primary節點和Secondary節點的片段,需先進行主備切換。
目前僅以下版本支援使用空間分析功能回收磁碟片段:
MongoDB 8.0:所有小版本。
MongoDB 7.0:所有小版本。
MongoDB 6.0:所有小版本。
MongoDB 5.0:所有小版本。
MongoDB 4.4:大於等於5.0.7版本。
MongoDB 4.2:大於等於4.0.23版本。
前提條件
執行個體的儲存引擎為WiredTiger。
注意事項
資料備份:回收磁碟片段前,建議對資料庫資料備份。
compact命令影響:compact是進行空間整理與回收的命令,可以進行磁碟片段回收。讀寫阻塞與效能影響
MongoDB 4.4之前的版本執行
compact命令會導致集合所屬的資料庫被鎖定,且該資料庫的讀寫操作將被阻塞。片段過多時,compact命令的執行時間會比較長,此時可能會出現Hidden節點複寫延遲大的風險。建議您在業務低峰期操作,並根據業務寫入情況適當調大Oplog大小,或者升級資料庫大版本至MongoDB 4.4及之後再進行片段回收操作。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執行個體,執行
compact命令的節點將維持在SECONDARY狀態,不會觸發重搭操作。
compact命令無效:以下情境可能會導致
compact命令執行無效,更多介紹請參見block_compact。物理集合大小小於1 MB。
片段率小於20%。
檔案前80%的儲存空間中,空閑儲存空間小於20%;檔案前90%的儲存空間中,空閑儲存空間小於10%。
回收時間:執行
compact命令回收磁碟片段所需的時間與集合資料量、系統負載等因素有關。其他:
執行
compact命令時,可能會出現釋放的儲存空間小於閒置儲存空間的情況。如果出現上述情況,請確保前一個compact命令執行完畢後再發起下一個,避免頻繁重複執行。compact命令可以在磁碟空間滿導致執行個體鎖定的情況下執行。
背景資訊
為什麼會產生磁碟片段?
形成:在刪除ApsaraDB for MongoDB執行個體的資料後,這些被刪除資料使用的儲存空間會被標記為空白閑,隨後寫入的新資料可能會被直接儲存到這部分閒置儲存空間中,也可能會先擴充檔案的儲存空間再儲存到檔案末尾。上述情況將導致一部分閒置儲存空間不會被使用,這些未被使用的空閑儲存空間被稱之為磁碟片段。
影響:磁碟片段越多,磁碟的有效利用率就越低。比如磁碟大小100GB,片段空間佔據20GB,業務資料佔據60GB,那麼資料庫執行個體的磁碟利用率為80%,但磁碟的有效利用率為60%。
什麼時候需要回收磁碟片段?
一次性刪除大量資料
在刪除大量資料後,這些文檔佔據的磁碟空間並不會被主動歸還給作業系統,而是優先用於承載後續可能的寫入,這可能導致磁碟上存在大量未被有效利用的片段空間。
重要手動刪除資料與自動到期(TTL)機制,均不會自動觸發磁碟片段回收,需要您手動回收磁碟片段。
長時間運行高寫入工作負載
如果您的執行個體長時間運行高寫入工作負載(例如,頻繁執行資料插入、更新、刪除等操作),隨著時間推移,磁碟上零散分布的片段化空間將不斷增加,從而累積產生大量磁碟片段。
磁碟空間緊張且確認有>20%的片段空間
當您的資料庫執行個體的磁碟空間變得緊張時(例如,磁碟利用率達到85%-90%以上),回收磁碟片段可以釋放被片段佔用的儲存空間,從而降低磁碟利用率並緩解磁碟空間壓力。
查看磁碟儲存空間
查看指定集合儲存空間狀況
您可以執行db.runCommand({collStats: <collection_name>}) 命令,查看指定集合的儲存空間狀況。部分關鍵字介紹如下:
size:表示集合的邏輯儲存大小。storageSize:表示集合的實體儲存體大小。freeStorageSize:表示磁碟片段中空閑並可以被回收的磁碟空間,ApsaraDB for MongoDB 4.4及以上版本支援查看。
在執行remove命令刪除文檔後,size的值會減少,但是storageSize的值不一定會減少。可觀察freeStorageSize在storageSize中的佔比,佔比率較高時,代表磁碟片段率較高。
關於size、storageSize和freeStorageSize關鍵字的更多資訊,請參見collStats-Output。
預估回收的磁碟片段空間
通過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組件中從節點(Secondary節點)的磁碟片段。
本操作在mongo shell和mongosh中執行存在一定差異,請根據您使用的用戶端來選擇對應的操作方法。
說明相比較mongosh 1.x版本,2.x版本新增了支援設定讀寫偏好參數。具體說明,請參見Read Preference。
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 1.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"}})mongosh 2.x
文法:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}},{readPreference: "secondary"})參數說明:
<Shard ID>:Shard組件的ID。說明您可以登入MongoDB管理主控台,在目標執行個體基本資料頁面的Shard列表地區查看Shard組件的ID。
<collection_name>:集合名稱。說明您可以通過
show tables命令查詢現有的集合。
樣本:
db.runCommand({runCommandOnShard:"d-2ze657bce53fb6d4","command":{compact:"test_collection"}}, { readPreference: "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}})
查看回收磁碟片段後資料庫佔用的磁碟空間。
db.stats()說明該命令可以直接複製執行,無需修改。
常見問題
Q:執行命令報錯,“Compaction interrupted on table:xxx due to cache eviction pressure' on server xxx. ”。
A:低版本的小規格執行個體在執行compact的過程中,可能因緩衝壓力而中途退出,建議在業務低峰期操作。