如何使 MongoDB `repairDatabase` 和 `compact` 命令与副本集一起工作?停机时间还可以
How to make MongoDB `repairDatabase` and `compact` commands work with replica-set? Downtime is ok
我们需要释放一些 MongoDB space,我们确定了 100Gb 以上的文档可以安全地从集合中删除。
因此我们将它们从具有此设置的测试环境中删除:
- mongodb 版本 3.0.1
- 无分片
- 1 个节点,无副本
- wiredtiger 引擎
完成后,我们发现磁盘上的space仍在使用,需要回收。我们找到了 this post 并且它帮助了我们:在 运行 两个
之后
db.runCommand({repairDatabase: 1})
和
db.runCommand({compact: collection-name })
我们释放了 100Gb +。
然后我们继续生产,忘记了设置是不同的,因为我们有 1 个副本节点:
- mongodb 版本 3.0.1
- 无分片
- 1个主节点,1个副本节点
- wiredtiger 引擎
删除文件后,我们运行
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 上的磁盘仍在使用,未被释放。
我们搜索了 运行 使用副本集 repairDatabase
和 compact
命令的解决方案,但建议的重点是避免停机,就好像那是唯一的问题一样。但是,我们可以安排停机时间,而我们的问题是命令无法按预期工作,因为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 的大量改进。
我们需要释放一些 MongoDB space,我们确定了 100Gb 以上的文档可以安全地从集合中删除。
因此我们将它们从具有此设置的测试环境中删除:
- mongodb 版本 3.0.1
- 无分片
- 1 个节点,无副本
- wiredtiger 引擎
完成后,我们发现磁盘上的space仍在使用,需要回收。我们找到了 this post 并且它帮助了我们:在 运行 两个
之后db.runCommand({repairDatabase: 1})
和
db.runCommand({compact: collection-name })
我们释放了 100Gb +。
然后我们继续生产,忘记了设置是不同的,因为我们有 1 个副本节点:
- mongodb 版本 3.0.1
- 无分片
- 1个主节点,1个副本节点
- wiredtiger 引擎
删除文件后,我们运行
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 上的磁盘仍在使用,未被释放。
我们搜索了 运行 使用副本集 repairDatabase
和 compact
命令的解决方案,但建议的重点是避免停机,就好像那是唯一的问题一样。但是,我们可以安排停机时间,而我们的问题是命令无法按预期工作,因为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 的大量改进。