52

是否可以修改 MongoDB oplog 并重播它?

一个错误导致更新应用于比预期更多的文档,覆盖了一些数据。数据已从备份中恢复并重新集成,因此实际上没有丢失任何内容,但我想知道是否有办法修改 oplog 以删除或修改有问题的更新并重播它。

我对 MongoDB 内部没有深入的了解,因此类似“你不明白它是如何工作的,就是这样”的信息性答案也将被考虑接受。

4

1 回答 1

108

应用程序或人为错误数据损坏的大问题之一是对主服务器的违规写入将立即复制到辅助服务器。

这是用户利用“slaveDelay”的原因之一 - 一个以固定时间延迟运行您的辅助节点之一的选项(当然,只有在您发现错误或错误的时间段内小于该次要延迟)。

如果您没有这样的设置,您必须依靠备份来重新创建您需要恢复到它们的预错误状态的记录的状态。

在数据的单独独立副本上执行所有操作 - 只有在验证所有内容都已正确重新创建之后,您才能将更正的数据移动到您的生产系统中。

能够做到这一点需要一个最近的备份副本(假设备份是 X 小时前的),并且集群上的 oplog 必须保存超过 X 小时的数据。我没有指定哪个节点的 oplog,因为(a)副本集的每个成员在 oplog 中具有相同的内容,并且(b)您的 oplog大小可能在不同的节点成员上不同,在这种情况下您要检查“最大”的一个。

因此,假设您最近的备份是 52 小时前的,但幸运的是,您有一个包含 75 小时数据的 oplog(耶)。

您已经意识到您的所有节点(主节点和辅助节点)都有“坏”数据,因此您要做的就是将此最新备份还原到新的 mongod 中。在这里,您可以将这些记录恢复到有问题的更新之前的状态 - 然后您可以将它们移动到当前主节点,然后将它们复制到所有辅助节点。

恢复备份时,通过以下命令创建 oplog 集合的 mongodump:

mongodump -d local -c oplog.rs -o oplogD

将 oplog 移动到它自己的目录,将其重命名为 oplog.bson:

mkdir oplogR
mv oplogD/local/oplog.rs.bson oplogR/oplog.bson

现在您需要找到“违规”操作。您可以使用 oplogR/oplog.bson 文件上的命令将 oplog 转储为人类可读的形式bsondump(然后使用 grep 或其他方法来查找“错误”更新)。或者,您可以通过shell 中的use local和命令查询副本集中的原始 oplog 。db.oplog.rs.find()

您的目标是找到此条目并记下其ts字段。

它可能看起来像这样:

"ts" : Timestamp( 1361497305, 2789 )

请注意,该mongorestore命令有两个选项,一个被调用--oplogReplay,另一个被调用oplogLimit。您现在将在恢复的独立服务器上重播此 oplog,但您将在此违规更新操作之前停止。

该命令将是(主机和端口是您新恢复的备份所在的位置):

mongorestore -h host --port NNNN --oplogReplay --oplogLimit 1361497305:2789 oplogR

这将从 oplogR 目录中的 oplog.bson 文件中恢复每个操作,该文件在具有 ts 值 Timestamp(1361497305, 2789) 的条目之前停止。

回想一下,您在单独的实例上执行此操作的原因是您可以验证还原和重放创建的正确数据 - 一旦您验证了它,您就可以将还原的记录写入真实主数据库中的适当位置(并允许复制传播将更正的记录发送到辅助服务器)。

于 2013-03-16T15:55:44.093 回答