【问题标题】:MongoDB Padding ClarificationMongoDB 填充说明
【发布时间】:2014-02-17 07:44:25
【问题描述】:

查看 capped collections 在 MongoDB 中的使用情况,我想到了以下语句:

"您可以在插入集合后更新文档。但是,这些更新 不能导致文档增长。如果更新操作导致文档 超出其原始大小,更新操作将失败。”

所以这本身听起来很合理,如果没有完全解释原因的话。它让我思考,“如果我不希望文档增长,但可能添加更多信息(即:$push 到数组),那么将文档填充到我的预期大小会有什么问题。”

所以我的前提再一次听起来很合理(无论如何对我来说),直到从FAQ on padding阅读这个片段。

警告不要在有上限的集合中手动填充文档。应用手册 填充到上限集合中的文档可能会破坏复制。此外,填充 如果您重新同步 MongoDB 实例,则不会保留。

这又引发了我的问题,“为什么会这样?”或者说具体点:

  1. 为什么要在这种无用的“破坏复制”中填充上限集合中的文档?

  2. 文档中是否有遗漏部分说明了明显的原因?或者这只是封顶系列内部运作的“黑暗魔法”? (可能与“不保留填充”部分有关)

  3. 或者这只是非常悲观,实际上没有理由你不能以这种方式填充? (至少在最近的版本中)。

如果有人能解释为什么这些陈述是正确的,我会很高兴。

P.S 虽然这不是严格编程,但我认为手动填充技术是一种编程技术,因此将问题留在这里.

【问题讨论】:

  • 我相信这是因为辅助节点不知道您的手动填充。它不会出现在 oplog 中

标签: mongodb padding


【解决方案1】:

为什么要在这种无用的“破坏复制”中填充上限集合中的文档?

我认为这里的文档可能有点过于谨慎(参见DOCS-1528)。 MongoDB 无法知道字段 padding_foobar 是否用于“手动填充”或包含系统关键信息,因此该技术通常有效,但是

警告是这样的:MongoDB initial 复制总是会紧紧地打包数据,所以当初始复制发生时你改变了大小文档,您以后将无法再次增长该文档。

一个例子(注意:我这里只使用内容大小,这是不正确的,因为字段名、类型 id、终止符和字符串长度也会占用空间,但这只会加强论证):

// 1. insert w/ 20 bytes of 'content'
insert({"name" : "john", "pad" : "0000000000000000"});

// 2. now we're performing an update, removing 16 bytes of padding, adding
//    3 bytes so we now have 7 bytes of 'content'
update({"name" : "john"}, {$unset: {"pad": 1}, $set: {"foo" : "bar"}});

// 3. at this point, we can easily grow the document again, as long as it doesn't
//    grow past its original size of 20 bytes of content
update({"name" : "john"}, {$set: {"foo" : "barfoobar"}});

现在,当在第 2 步之后发生初始复制时,复制的文档没有填充字段,因此副本上只有 7 个字节的“内容大小”。在这种情况下,第 3 步)中的操作将失败,因为它使文档增长超过了副本的文档“原始大小”,而与主文档的原始大小不匹配。

换句话说,当且仅当您的更新严格保持或减小对象大小时,该技术才有效。您是否可以确保在您的应用程序逻辑中(例如,因为这样的文档只有一次更新)只有您可以回答。

【讨论】:

  • 结构良好的答案。但是,除非我(“一瓶酒”)智商下降了很多,否则这怎么不能加强我原来陈述的 3 点?除非您真正要说的是 somewhere 正在跳过“填充”阶段。在我看来,这对复制概念有点适得其反,如果不是所有操作都被重放。因此,如果 的情况,它似乎仍然不正确。
  • 就像我写的那样,文档希望你保持谨慎(阅读引用的 Jira 票证中的讨论),所以是的,你可以做到(这也是我在最后一段中所说的),但请记住,初始副本集同步打破这一点。因此,如果您必须在运行一年或副本中断后添加第三个副本,除非您手动复制数据文件并且文件在任何文档缩小之前就在那里,否则它将失败。这使得抽象非常容易泄漏(devops 必须了解并了解这一点)。用更专业的术语来说,初始副本集同步打破了 oplog 的幂等性。
  • 首先,很抱歉听到风滚草的声音,但我希望这个问题能引起相关人员的更多关注,尤其是经常来这里的 MongoDB 员工。我的意思是,“至少在评论中”。虽然您在后续评论中的“最后一句话”确实在推理中最重要,但我的逻辑是,在问题的“精神”中,我们正在谈论“封顶集合”,因此像这样的边缘情况不应该对一般用途有效。前提仍然是合理的,即警告是 FUD。没有冒犯。
  • 因此,只需尝试记录在边缘情况之外,您可以在上限集合中的文档上使用 $push 等运算符。由于一般用例是文档应该是短暂的。任何其他错误处理由开发人员决定。
  • 如果您想联系 MongoDB 开发人员,可以使用我发布的 Jira 的链接。我会小心地将初始副本集同步声明为“边缘情况”。看起来你正在寻找一个告诉你“去吧,别担心”的人,但我不会是那个人。
猜你喜欢
  • 1970-01-01
  • 2013-02-07
  • 1970-01-01
  • 2018-03-28
  • 2021-01-25
  • 2019-06-25
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多