Mongoose版本控制:什么时候可以安全地禁用它?

23
根据文档: 每个由Mongoose首次创建的文档都会设置versionKey属性。该键的值包含文档的内部修订版本。此文档属性的名称是可配置的,默认为__v。如果这与您的应用程序发生冲突,可以进行配置。 除非您知道自己在做什么,请勿将文档版本控制设置为false。但我好奇,在哪些情况下禁用此功能是安全的?

1
这篇博客文章讨论了在子文档数组中按位置访问元素的情况。但是,mongoose实际上使用id而不是位置。所以我也不确定:http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning - Behlül
1个回答

58

版本键的目的是进行乐观锁定。

启用后,每当更新文档时,版本值会自动递增。

这使得应用程序代码能够测试在获取(例如获取版本键42)和随后的更新(确保版本值仍为42)之间是否已经进行了更改。 如果版本键具有不同的值(例如43,因为对文档进行了更新),则您的应用程序代码可以处理并发修改。

在关系数据库中,通常使用相同的概念,而不是会带来恶劣性能的悲观锁定。所有体面的ORM都提供此功能。例如,在Java中实现的对象数据库ObjectDB文档中很好地描述了它。

博客文章链接到Behlül的评论中展示了乐观锁的有用性,并提供了具体的示例,但仅适用于数组更改,请参见下文。

相反地,这里有一个简单的案例,其中它是无用的:用户配置文件只能由其所有者编辑。在这种情况下,您可以摆脱乐观锁定并假设最后一次编辑总是获胜。
因此,只有您知道您的应用程序是否需要乐观锁定。逐个用例使用。
Mongoose的情况有些特殊。
仅对数组启用乐观锁定,因为内部存储格式使用位置索引。这是问题的描述 blog post 链接在问题的评论中。我在mongoose-orm邮件列表中找到了explanation ,非常清晰:如果您需要其他字段的乐观锁定,则需要自行处理。
这里有一个gist,展示了如何实现一个“重试”策略来进行add操作。再次强调,如何处理取决于您的用例,但这应该足以让您入门。
我希望这能澄清问题。
祝好

1
如果我们使用$in运算符来访问子文档,是否需要版本控制呢?对我来说,这似乎与访问父文档没有什么不同。 - Behlül
再次强调,这取决于使用情况。当使用$in运算符时,您会缩小并发修改窗口,但请记住它仍然是开放的。 - eskatos
2
@esKotos,我认为您的新更新的答案看起来有歧义,因为当我们仅更新任何非数组字段时,版本控制不起作用。 - Sandeep Sharma
@esKotos 除此之外,如果我不修改数组字段,想要实现这个功能怎么办? - Sandeep Sharma
2
@SandeepSharma 在任何 save() 之前,您需要调用 document.increment()。这将发出增加版本的信号,以防保存成功(验证通过且没有版本冲突)。 - Cédric NICOLAS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接