它在常见问题解答部分http://docs.mongodb.org/manual/faq/concurrency/#faq-concurrency-operations-locks中指出:
“(... eval需要...)写锁定。如果与nolock lock选项一起使用,eval选项不会进行写锁定,也不能将数据写入数据库。”
在eval文档中,我们可以读到:
“(... eval选项...)nolock不会影响JavaScript代码中的操作是否采用写锁定。”
我也检查过,可以使用nolock选项从eval写入数据库。
这是否意味着:
使用写入数据库的eval即。通过db.coll.update
等与nolock选项不会发出错误,但它被禁止,即。行为未定义或可能锁定数据库?如果是这种情况,为什么在红色的eval文档中没有提到它?
使用eval可以使用nolock选项写入数据库,并且在eval中发出命令,如db.coll.insert
或db.coll.update
将使用自己的写锁,但整个eval将保持读锁定。在这种情况下,不是不必要的nolock选项,并且应该始终默认为false?
答案 0 :(得分:1)
查看上下文documentation中的整个陈述:
- 默认情况下, eval 在评估JavaScript函数之前会进行全局写锁定。因此,当eval操作运行时, eval 会阻止对数据库的所有其他读写操作。在 eval 命令上将 nolock 设置为 true ,以防止 eval 命令在评估之前获取全局写锁定JavaScript的。 nolock 不会影响JavaScript代码中的操作是否采用写锁定。
所以这里的默认情况有一个目的,即当调用它来对数据执行某种“批量”更改时通常会尝试什么,作为一个概念,你通常不会改变其他的东西。这是在继续。因此,默认情况下有获得锁定的原因。
在 nolock 的情况下,您需要考虑 eval 的某些用法实际上可能与读取或写入数据无关。我自己真的没有看到原因,但我遇到过一些人们想要这样做的案例。在这种情况下,获得一个否则会因为没有特殊原因而被阻止的锁是没有意义的。
如果你设置 nolock 但是仍然继续更新数据,那么你必须考虑下面实际发生的事情。当然,您正在执行JavaScript,并且只应获取对当前操作显式的写入的锁(并且可能仅在集合级别)。似乎是合理的。
但是你也在同一个JavaScript执行线程中执行该操作,而不是像“for”循环那样运行。虽然每个操作在某种程度上应该在技术上屈服,但实际情况是在该执行线程中对此没有太多控制,最终结果将近似等同于首先可以获得的全局锁定。
所有这些都说,使用 eval 应该是“最后的手段”措施,实际上只是为了解决数据维护和迁移的“一次性”问题。在生产中继续使用可能根本不是一个好主意,并可能导致问题。
总是考虑替代方案,或多或少包含在这里: