我希望特定模型的所有数据库交互都通过集群中的mongo主数据库,因此我将模型设置为使用强一致性。
class Photo
include Mongoid::Document
with consistency: :strong
field :number, type: Integer
# let's say a photo number is unique in the db
validate :unique_number
end
但这似乎不起作用,因为当我将两张照片非常靠近地保存在一起时,我仍然遇到验证错误。
photo1 # db has number=1 for this object
photo1.update_attributes(number: 2)
photo2.number = 1
photo2.save! # <= this raises a validation exception
我对强烈一致性的理解是,这里不应该是一场比赛。它应该进行写入然后进行读取,因为它完全不在主要部分,所以不应该是冲突。我错过了什么?
答案 0 :(得分:0)
您所遇到的区域似乎是持久性。 update_attributes正在对文档进行原子更改,看起来它没有更新持久化的photo1.Your photo2验证是从持久性内部(即在rails服务器上而不是在mongo中)触发的,并且正在查看它的记录具有。如果您在photo1.update_attributes之后运行photo1.reload,这可能会为您排序。
自从我使用mongoid 3,4以来已经有一段时间了,有一段时间它已成为主流,最近升级到5.你不会在mongoid 4中找到这种类型的问题。
如果重新加载没有帮助,请输出photo2.errors,以便我可以为您指出问题。
答案 1 :(得分:0)
事实证明,在班级调用with(consistency: :strong)
只会将其应用于下一个查询。因此,在加载类时调用类方法,为第一个查询设置强一致性,
但后续查询不会触发相同的类方法,使其持久性操作与最终一致性一起运行。来自Mongoid 3.1.7 documentation:
告诉下一个持久性[原文如此]操作存储在特定的集合,数据库或会话中。
此方法不强制执行可传入的持久性选项(如类中的其他一些方法),因此我们也可以传入consistency: :strong
。
为了将其应用于每个*持久性操作,我将其添加到default_scope
。
class App
default_scope -> { with(consistency: :strong); where({}) }
end
在这种情况下,默认范围期望返回一个Mongoid Criteria对象,因此我们在为正在进行的持久性操作设置一致性级别后返回noop where
子句。
*如果开发者决定致电unscoped
并剥离default_scope
,则不会应用此功能。