回收磁盘空间
在删除 MongoDB 实例中的数据后,这些被删除数据使用的存储空间会被标记为空闲,随后相同集合写入的新数据通常会被直接存储到这部分空闲的存储空间中。但无法被其他集合复用这部分空闲存储空间,这些未被使用的空闲存储空间被称之为磁盘碎片,磁盘碎片越多,磁盘利用率就越低。
回收磁盘空间有两种方法:使用 compact
命令和重建数据文件。
-
compact
命令:这是集合级别的操作,需要逐个集合进行压缩处理。 -
重建数据文件:这是数据库实例级别的操作,针对整个数据库执行,通常更全面。
compact
注意事项
-
操作之前,请务必先对数据库数据进行完整备份。
-
MongoDB 4.4之前的版本执行
compact
命令会导致集合所属的数据库被锁定,且该数据库的读写操作将被阻塞,建议您在业务低峰期或升级版本后操作。受阻塞的具体介绍,请参见 MongoDB 官方文档。-
执行
compact
命令回收磁盘碎片所需的时间与集合数据量、系统负载、磁盘性能等因素有关,执行期间也会对CPU、内存占用也有一定增长。 -
小于 4.4.9 的版本,正在执行
compact
命令的节点会强制进入 RECOVERING 状态,如果持续时间过长,该节点会被将无法继续同步PRIMARY
节点数据。 -
4.4.9 - 4.4.17 之间的 MongoDB 版本,执行
compact
命令的节点则会保持在SECONDARY
状态,但是依旧运行中状态依旧无法同步PRIMARY
节点数据。 -
4.4.17 之后的版本在执行
compact
时SECONDARY
节点会持续复制PRIMARY
节点数据。(建议在大于 4.4.17 的版本下操作compact
)
-
-
以下场景可能会导致
compact
命令执行无效,更多介绍请参见开源代码。-
物理集合大小小于 1 MB。
-
文件前 80% 的存储空间中,空闲存储空间小于 20%;文件前 90% 的存储空间中,空闲存储空间小于 10%。
-
-
执行
compact
命令时,可能会出现释放的存储空间小于空闲的存储空间的情况。如果出现上述情况,您可以尝试重复执行compact
命令来释放磁盘碎片,但不建议您频繁执行compact
命令。
预估回收的磁盘碎片空间
-
将数据库切换至集合所在的数据库。
use database_name
database_name
为集合所在的数据库名称。
-
查看集合需回收的磁盘碎片空间。
db.collection_name.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
collection_name
为集合名称。
返回结果如下:
1485426688
该返回结果表示预估回收的磁盘碎片空间为 1485426688 Byte。
回收单节点或副本集实例的磁盘碎片
单节点
单节点实例只有一个节点,所以只需针对这个实例点执行 compact
命令即可。
副本集
副本集实例具有多个节点,执行顺序:
-
在其中一个
SECONDARY
节点执行compact
。compact
完成后,依次在每个剩余的SECONDARY
节点上重复此操作。 -
重新分配主节点,在
PRIMARY
节点,使用rs.stepDown()
方法触发重新选举PRIMARY
节点。当PRIMARY
节点转变为SECONDARY
状态并成功选举出新PRIMARY
节点后,即可执行compact
命令。-
如果需要在
PRIMARY
节点强制执行compact
命令,则需要添加foce
参数,例如:db.runCommand({compact:"collection_name",force:true})
-
compact 操作方法
-
通过 Mongo Shell 连接数据库节点。
-
将数据库切换至集合所在的数据库。
use database_name
database_name
为集合所在的数据库名称。
-
指定集合执行
compact
,回收集合的磁盘碎片。db.runCommand({compact:"collection_name"})
collection_name
为集合名称。
执行成功的返回结果如下:
{ "ok" : 1 }
重建数据文件
注意事项
-
操作之前,请务必先对数据库数据进行完整备份。
-
重建数据文件所需的时间与集合数据量、系统负载、磁盘性能等因素有关。
单节点
-
停止应用服务
-
停止 MongoDB 数据库
-
使用
mongod
的--repair
参数来重建数据文件,从而回收磁盘空间。示例:
mongod --repair --dbpath /data/mongodb/
-
/data/mongodb/
为 MongoDB 数据存储目录 -
执行期间请勿中断操作,否则可能会影响数据完整性,导致数据库无法启动。
-
-
启动 MongoDB 数据库
副本集
通过删除 SECONDARY
节点上的数据,并利用 MongoDB 副本集的内部重新同步机制,可以重建数据文件,从而回收磁盘空间。
-
在任意一个
SECONDARY
节点上执行以下命令,删除当前节点数据(排除keyfile
文件)find /data/mongodb/ -mindepth 1 ! -name 'keyfile' -exec rm -rf {} +
- 该命令排除
/data/mongodb/
目录下的keyfile
文件,删除其他所有文件和子目录。
- 该命令排除
-
重启当前 MongoDB 节点
-
使用
rs.status()
命令检查节点状态。在同步过程中,节点状态会显示为STARTUP2
,同步完成后会变为SECONDARY
。 -
当上一个节点完成同步并且节点状态变为
SECONDARY
后,可以在剩余的SECONDARY
节点上依次重复该操作。 -
最后,在
PRIMARY
节点上使用rs.stepDown()
方法触发重新选举。当PRIMARY
节点转变为SECONDARY
状态并成功选举出新PRIMARY
节点后,可以对该节点执行上述相同操作。