在 MongoDB 中的空间回收方面存在相当大的混乱,一些推荐的做法在某些部署类型中是非常危险的。更多详情如下:
TL;DR repairDatabase 尝试从试图从磁盘损坏中恢复的独立 MongoDB 部署中挽救数据。如果它恢复空间,那纯粹是副作用。回收空间绝不应该是运行repairDatabase 的首要考虑因素。
在独立节点中恢复空间
WiredTiger: 对于带有 WiredTiger 的独立节点,运行 compact 将向操作系统释放空间,但需要注意的是:MongoDB 3.0.x 上 WiredTiger 上的 compact 命令受此影响错误:SERVER-21833 已在 MongoDB 3.2.3 中修复。在此版本之前,WiredTiger 上的compact 可能会静默失败。
MMAPv1:由于 MMAPv1 的工作方式,没有安全且受支持的方法可以使用 MMAPv1 存储引擎来恢复空间。 MMAPv1 中的compact 将对数据文件进行碎片整理,可能会为新文档腾出更多空间,但不会将空间释放回操作系统。
如果您完全了解此潜在危险命令的后果(见下文),您可能能够运行repairDatabase,因为repairDatabase基本上重写了整个数据库通过丢弃损坏的文档。作为一个副作用,这将创建新的 MMAPv1 数据文件,其中没有任何碎片,并将空间释放回操作系统。
对于不太冒险的方法,在 MMAPv1 部署中也可以运行 mongodump 和 mongorestore,具体取决于您的部署规模。
恢复副本集中的空间
对于副本集配置,恢复空间的最佳和最安全的方法是对 WiredTiger 和 MMAPv1 执行initial sync。
如果您需要从集合中的所有节点恢复空间,您可以执行滚动初始同步。也就是说,在每个辅助节点上执行初始同步,然后最终降级主节点并对其执行初始同步。滚动初始同步方法是执行副本集维护的最安全方法,而且它还没有停机作为奖励。
请注意,进行滚动初始同步的可行性还取决于您的部署规模。对于非常大的部署,进行初始同步可能不可行,因此您的选择会受到更多限制。如果使用 WiredTiger,您也许可以从集合中取出一个辅助,将其作为独立启动,在其上运行 compact,然后将其重新加入集合。
关于repairDatabase
请不要在副本集节点上运行repairDatabase。这是非常危险的,正如repairDatabase page 中提到的,并在下面进行了更详细的描述。
名称repairDatabase 有点误导,因为该命令不会尝试修复任何内容。该命令旨在在独立节点上出现磁盘损坏时使用,这可能导致文档损坏。
repairDatabase 命令可以更准确地描述为“打捞数据库”。也就是说,它通过丢弃损坏的文档来重新创建数据库,以尝试使数据库进入可以启动它并从中挽救完整文档的状态。
在 MMAPv1 部署中,数据库文件的这种重建会为操作系统释放空间作为副作用。向操作系统释放空间从来都不是目的。
repairDatabase 在副本集上的后果
在副本集中,MongoDB 期望集合中的所有节点都包含相同的数据。如果您在副本集节点上运行repairDatabase,则该节点有可能包含未检测到的损坏,repairDatabase 将尽职尽责地为您删除损坏的文档。
可以预见的是,这使得该节点包含与集合的其余部分不同的数据集。如果更新恰好针对该单个文档,则整个集合可能会崩溃。
更糟糕的是,这种情况完全有可能长期处于休眠状态,只是突然袭击而没有明显的原因。