mongodb獲取空閒磁盤空間

這篇文章 mongodb使用內存和硬盤特性 我們介紹過mongodb刪除數據後,並不會釋放磁盤空間。大部分數據庫爲了性能都會這樣做,比如mysql也是。不過mysql可以整理磁盤空間,把空閒的磁盤釋放掉,還給操作系統,但是mongodb卻不會。雖然說mongodb也有整理磁盤的接口調用(compact),但是它並不是釋放所有的空閒空間,只是把很少的部分空間釋放,繼續可以忽略不計。並且compact時會鎖表,導致數據庫暫時不可用,也要謹慎使用。

如果磁盤空間不可以釋放,如何維護mongodb的長時間穩定運行呢?實際上我們不需要mongodb把磁盤還給系統,只需要mongodb佔用的磁盤大小一直維持在一個範圍內即可(比如500G)。相當於mongodb一開始就劃分了這麼大的空間,後續不再增長,達到限額就把舊的數據覆蓋即可。

要想實現mongodb對磁盤的佔用維持在一個穩定的範圍,定期刪除數據是不可避免的。問題在與什麼時候刪除,刪除多少數據呢?我們就需要知道當前mongodb到底佔用了多少。雖然分配了500G,但是隻佔用了100G,所以不需要刪除;如果佔用空間快到500G了,我們就需要刪除部分數據,因爲超過500G後,mongodb就會分配新的磁盤,並且無法釋放(除非導出數據庫再導入)。

存儲狀態查詢

mongodb官方提供了查看數據庫或者集合狀態的方法

db.stats()
db.xxx.stats()
db collections views objects avgObjSize dataSize storageSize indexes indexSize totalSize scaleFactor fsUsedSize fsTotalSize ok
xxx 152 0 256646 4953.99530481675 1271423079 477196288 308 14938112 492134400 1 1222409334784 1897374105600 1

ns size count avgObjSize numOrphanDocs storageSize freeStorageSize capped wiredTiger nindexes indexBuilds totalIndexSize totalSize indexSizes scaleFactor ok
xxx 215551960 6478 33274 0 59797504 1327104 false (Document) 15 Fields 2 (Array) 0 Elements 286720 60084224 (Document) 2 Fields 1 1

每個表示大小的單位取決於scaleFactor,基礎都是字節,scaleFactor就是獲取的字節數除以幾,爲了方便統計MB或者GB

  • db 數據庫名

  • collections 數據庫有多少集合

  • views 數據庫有多少視圖

  • objects 數據庫有多少條數據

  • avgObjSize 每條就平均大小(字節)

  • dataSize 數據大小(字節),注意並不是磁盤佔用大小,因爲有壓縮

  • storageSize 磁盤佔用大小(數據)(字節)

  • indexes 索引數量

  • indexSize 索引磁盤佔用大小(字節)

  • totalSize 全部磁盤佔用大小(字節)(索引加數據)

  • scaleFactor 上面統計字節數再相除的除數,主要用作如果不想統計字節,可以設置爲1024,就會自動除以1024,變成K,MB GB依此類推

  • fsUsedSize mongo佔用的總的空間大小。不僅僅是數據庫,包括mongo自身的bin文件和日誌等

  • fsTotalSize mongo申請的總的磁盤大小。上面的只是用的到,有的磁盤空間已經申請了,但是還沒用。

  • ns 集合名

  • size 記錄在內存中未壓縮的數據佔用空間

  • count 數據條數

  • freeStorageSize 分配了磁盤空間,但是還未使用的大小(字節)

  • totalIndexSize 索引佔用的大小(字節)

空閒狀態查詢

上面只是展示了佔用了多少磁盤空間,mongodb提供的這兩個查看數據庫或者集合狀態的api,可以傳遞參數,獲取空閒可用的空間大小。

db.runCommand(
   {
     dbStats: 1,
     freeStorage: 1
   }
)
db collections views objects avgObjSize dataSize storageSize freeStorageSize indexes indexSize indexFreeStorageSize totalSize totalFreeStorageSize scaleFactor fsUsedSize fsTotalSize ok
xxx 152 0 2498923 916.97596161542 978820957 477196288 241803264 308 14921728 4743168 492118016 246546432 1 1222521229312 1897374105600 1

我們看到多了freeStorageSize indexFreeStorageSize totalFreeStorageSize,我們增加刪除一下數據,看一下變化。

db collections views objects avgObjSize dataSize storageSize freeStorageSize indexes indexSize indexFreeStorageSize totalSize totalFreeStorageSize scaleFactor fsUsedSize fsTotalSize ok
xxx 152 0 249892 3916.97596161542 978820957 477196288 241803264 308 14921728 4743168 492118016 246546432 1 1222521229312 1897374105600 1
xxx 152 0 249962 3918.08719725398 979372912 477196288 241803264 308 14921728 4743168 492118016 246546432 1 1222543265792 1897374105600 1
xxx 152 0 249968 3917.99706762466 979373891 477196288 241688576 308 14921728 4734976 492118016 246423552 1 1222545735680 1897374105600 1
xxx 152 0 247958 3747.61018398277 929249926 477196288 241688576 308 14938112 4743168 492134400 246431744 1 1222549508096 1897374105600 1
xxx 152 0 247961 3747.56663749541 929250371 477196288 254107648 308 14921728 4784128 492118016 258891776 1 1222551937024 1897374105600 1

第1條是原始數據狀態,第2條是增加了部分數據後直接查詢的狀態,我們看到objects增加了,從249892增加到249962,但是freeStorageSize並沒有變,這是因爲mongodb寫入數據或者同步信息有延遲,這是正常的。又插入了幾條數據,第3條再查詢,就看到數據更新了,freeStorageSize indexFreeStorageSize totalFreeStorageSize都有增加。4和5是對數據刪除,可以看到freeStorageSize indexFreeStorageSize totalFreeStorageSize也都有相應減少。

storageSize始終沒有變換,就是因爲mongodb還有空閒可用的空間,插入的時候也不會增加,刪除也不會釋放。

https://www.mongodb.com/docs/manual/faq/storage/#faq-disk-size
https://www.mongodb.com/docs/manual/reference/command/dbStats/#mongodb-dbcommand-dbcmd.dbStats
https://www.mongodb.com/docs/manual/reference/method/db.stats/
https://www.mongodb.com/docs/manual/reference/command/collStats/#mongodb-dbcommand-dbcmd.collStats
https://www.mongodb.com/docs/manual/reference/method/db.collection.stats/#mongodb-method-db.collection.stats

MongoServerError: scale has to be a number > 0

如果我們使用db.stats({scale: 1, freeStorage: 1})就會報上面的錯誤,按照官方的描述,好像這個實現還有問題。因爲db.stats()是對db.runCommand({dbStats: 1})的封裝,可能部分功能還沒有實現,所以只能使用runCommand。

https://jira.mongodb.org/browse/MONGOSH-1108

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章