Eval那邪恶吗?

时间:2013-04-05 15:54:15

标签: mongodb eval

我理解eval会锁定整个数据库,这对吞吐量不利 - 但是我的情况是必须隔离涉及多个文档的特定事务。

因为该事务不经常发生并且相当快(对索引查询进行了一些更新),所以我考虑使用eval来执行它。

他们应该注意到的任何陷阱(我看过几个eval =邪恶的帖子,但没有太多解释)? 如果数据库是副本集的一部分,它会有所不同吗?

1 个答案:

答案 0 :(得分:5)

许多开发人员建议使用eval是“邪恶的”,因为他们明显的安全问题是在MongoDB实例的上下文中执行的潜在未经过清理的JavaScript代码。通常,MongoDB不受那些类型的注入攻击的影响。

通过eval命令在MongoDB中使用JavaScript的一些性能问题在版本2.4中得到了缓解,因为多个JavaScript操作可以同时执行(取决于{{的设置) 1}}选项)。但是默认情况下,它需要一个全局锁定(这是你特别想要的)。

当使用nolock尝试对多个文档执行(类似ACID)事务更新时,有一个主要问题。最大的问题是,如果所有操作都必须成功使数据处于一致状态,那么开发人员就会面临操作中途发生故障可能导致部分完全更新数据库的风险(如硬件故障)例如)。根据正在执行的工作的性质,复制设置等,数据可能是正常的,也可能不是。

对于因部分完成eval操作而可能发生数据库损坏的情况,我建议考虑替代架构设计并避免使用eval。这并不是说它不会在99.9999%的时间内起作用,而是由你最终决定是否值得冒这个风险。

在您描述的情况下,有几个选项:

eval

{ version: 7, isCurrent: true} 文档成为最新文档时,您可以例如:

  • 创建包含当前版本的第二个文档,这将是一个原子集操作。这意味着所有读取都可能需要首先阅读“查找当前版本”文档,然后阅读完整文档。
  • 使用时间戳代替version 8值。根据时间戳查找最新文档(如果需要,当您设置当前文档时,您的代码可以清除旧文档的字段)