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

posted @ 2023-11-01 11:32  秋来叶黄  阅读(308)  评论(0编辑  收藏  举报