mongoDB释放磁盘占用

在mongo中删除数据并不会直接释放磁盘,而是产生很多碎片。这些碎片会被mongo继续利用。当有新数据插入时,会重复利用这些碎片,而不需要新申请磁盘空间。

但是这会导致的问题是,磁盘可能一直处于高水位的使用水平,对运维来说是一个定时炸弹。因为碎片只会被所属的库使用,但我们经常会新建很多库,这就导致磁盘越来越紧张。

目前我摸索出的是三种方法

1,将备节点清空,重新同步。

在备节点同步的过程中,碎片空间会被整理。备节点同步过去的是完全的数据和索引。

之后再进行一次主备切换。

使备节点成为主节点。

再将主节点数据清空,同步一次。

最终使主备都达到释放碎片的目的。

优点:服务一直可用

缺点:动作过大。要保证同步过程在同步窗口之内。建议将oplog尽量设置大一点

2,使用compact命令

compact是mongo中的压缩命令。可以整理删除数据产生的碎片。

在WiredTiger 数据库引擎下,该命令会将整理出的空间释放给操作系统。

在MMAPv1引擎下,compact会整理碎片,重建索引,但不会将未使用的空间释放给系统,后续新插入的数据依然可以使用这些空间

命令:

进入要执行的数据库

db.runCommand({ compact: <collection name>,force:<boolen> } )

对主备节点分别执行一次该命令

在复制集模式下的一些注意:

该命令会阻塞运行该命令的库,一定要选择好执行的时间

compact命令不会自动复制到secondary节点执行,compact在每个节点成员中都是独立的,在Primary,secondary中执行时都要使用force参数,

当在secondary的collection上执行compact命令时,此secondary节点会变成RECOVERING状态,且无法提供读操作

在capped collection中不必使用compact命令,因为它本身就是固定空间

实验:

当前库占了大约5.8G的磁盘

「干货」mongoDB释放磁盘占用

然后我删除了部分数据

clipboard.png

shard1:PRIMARY> db.runCommand({ compact: "fs.files"} )

{

"ok" : 0,

"errmsg" : "will not run compact on an active replica set primary as this is a slow blocking operation. use force:true to force"

}

需要加force:true
shard1:PRIMARY> db.runCommand({ compact: "fs.files",force:true} )
shard1:PRIMARY> db.runCommand({ compact: "fs.chunks",force:true} )

这里会卡很久,数据库操作会被锁住

clipboard2.png

实践证明:确实能够压缩

3,做repairDatabase

这个命令我没有尝试,谨慎使用。

做repairDatabase要求剩余磁盘要足够大。

但是当我的磁盘告警时,已经不会有足够的磁盘做repairDatabase了

db.runCommand({repairDatabase:1})

注:这个命令一定要谨慎使用,能不用的情况下尽量不用,因为会花费很多时间和性能

官网的一句话是这样说的:

The repairDatabase command compacts all collections in the database. It is identical to running the compact command on each collection individually

不建议直接repairDatabase,不如对需要做压缩的集合进行compact

总结

个人觉得mongo的这种机制真的很蛋疼。

大家还有没有什么好方法,欢迎交流

推荐阅读更多精彩内容