mongodb获取空闲磁盘空间

发布时间 2023-11-01 11:40:20作者: 秋来叶黄

这篇文章 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		249892	3916.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
1 xxx	 152			0		249892	3916.97596161542	978820957	477196288	241803264		308		14921728	4743168					492118016	246546432				1			1222521229312	1897374105600	1
2 xxx	 152			0		249962	3918.08719725398	979372912	477196288	241803264		308		14921728	4743168					492118016	246546432				1			1222543265792	1897374105600	1
3 xxx	 152			0		249968	3917.99706762466	979373891	477196288	241688576		308		14921728	4734976					492118016	246423552				1			1222545735680	1897374105600	1
4 xxx	 152			0		247958	3747.61018398277	929249926	477196288	241688576		308		14938112	4743168					492134400	246431744				1			1222549508096	1897374105600	1
5 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