如何使 MongoDB `repairDatabase` 和 `compact` 命令与副本集一起工作?停机时间还可以

How to make MongoDB `repairDatabase` and `compact` commands work with replica-set? Downtime is ok

我们需要释放一些 MongoDB space,我们确定了 100Gb 以上的文档可以安全地从集合中删除。

因此我们将它们从具有此设置的测试环境中删除:

完成后,我们发现磁盘上的space仍在使用,需要回收。我们找到了 this post 并且它帮助了我们:在 运行 两个

之后
db.runCommand({repairDatabase: 1})

db.runCommand({compact: collection-name })

我们释放了 100Gb +。

然后我们继续生产,忘记了设置是不同的,因为我们有 1 个副本节点:

删除文件后,我们运行

db.runCommand({repairDatabase: 1})

并收到 OK 消息(过了一会儿,10 分钟 +)。我们尝试了 运行ning

db.runCommand({compact: collection-name })

并得到这个错误:

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

所以我们运行

db.runCommand({compact: collection-name, force: true })

并收到 OK 消息(几乎立即),但 space 上的磁盘仍在使用,未被释放。

我们搜索了 运行 使用副本集 repairDatabasecompact 命令的解决方案,但建议的重点是避免停机,就好像那是唯一的问题一样。但是,我们可以安排停机时间,而我们的问题是命令无法按预期工作,因为space 实际上并未回收.

我们做错了什么?

对于副本集配置,恢复 space 的最佳和最安全方法是执行 initial sync。如果您需要从集合中的所有节点恢复 space,您可以执行滚动初始同步。也就是说,在最终降级主服务器并对其执行初始同步之前,在每个辅助服务器上执行初始同步。

请注意,滚动初始同步只有在您的部署包含至少三个节点副本集时才有可能(原因我将在下面描述)。

滚动初始同步方法是执行副本集维护的最安全方法,而且它还没有停机时间作为奖励。

话虽如此,但有一些事情值得一提:

关于compact

MongoDB 3.0.x 上 WiredTiger 上的 compact 命令受此错误影响:SERVER-21833 已在 MongoDB 3.2.3 中修复.在此版本之前,WiredTiger 上的 compact 可能会自动失败。

关于repairDatabase

请不要在副本集节点上 运行 repairDatabase强烈不推荐,如repairDatabase page中所述。名称 repairDatabase 有点误导,因为该命令不会尝试修复任何东西。该命令旨在在磁盘损坏时使用,这可能会导致文件损坏。

repairDatabase 命令可以更准确地描述为“挽救数据库”。也就是说,它通过丢弃损坏的文档来重新创建数据库,试图使数据库进入可以启动它并从中挽救完整文档的状态。

在副本集中,MongoDB 期望该集中的所有节点都包含相同的数据。如果您 运行 repairDatabase 在副本集节点上,则该节点有可能包含未检测到的损坏,并且 repairDatabase 将尽职地删除损坏的文档。可以预见的是,这使得该节点包含与该集合的其余部分不同的数据集。如果更新碰巧发生在那个单一的文档上,整个集合可能会崩溃。更糟糕的是,这种情况完全有可能长期处于休眠状态,然后突然无缘无故地发作。

关于您的设置:

我注意到在您的生产环境中,您创建了一个包含两个节点的副本集。不推荐这种设置,因为单个节点的故障会使剩余节点成为辅助节点,从而不允许写入该集合。

由于 MongoDB 高可用性的工作方式(参见 Replica Set Election), it's strongly recommended to deploy three data-bearing nodes at a minimum, or at least add an arbiter node (see Replica Set Members),因此您的副本集包含奇数个成员。

副本集中只有两个成员也会使滚动 upgrades/initial sync/maintenance 在某些情况下变得更加困难甚至不可能。

MongoDB 3.0.1 于 March 17, 2015 发布,距撰写本文时已有 2 年多了。如果您被迫使用 MongoDB 3.0 系列,请考虑迁移到 3.0.15。或者更好的是,到 3.4.7(截至 2017 年 8 月 10 日的最新版本),其中包含对 3.0.1 的大量改进。