3

我有一个使用 Mongoid 的 find_or_create_by 方法的网络应用程序。

poll = Poll.find_or_create_by(fields)

在我们投入生产之前,我正在尝试运行失败场景,我突然想到多个用户可以尝试使用此方法访问此资源。它是否有可能创建同一对象的多个实例?我能做些什么来防止这种情况发生?

4

2 回答 2

2

免责声明:我是 Mongoid 和 Rails 的新手,所以我可能完全错了。

查看modifiable.rbmany.rb它似乎没有锁定任何资源。

在我看来,它只是执行“where().first”查询,然后如果没有返回任何内容,则执行“create”查询:

 def find_or(method, attrs = {}, &block)
    where(attrs).first || send(method, attrs, &block)
  end

对于 find_or_create_by,“send”会调用“create_document”:

def create_document(method, attrs = nil, &block)
    klass.__send__(method,
      selector.reduce(attrs || {}) do |hash, (key, value)|
        unless key.to_s =~ /\$/ || value.is_a?(Hash)
          hash[key] = value
        end
        hash
      end, &block)
  end

结论:对我来说,这似乎是一种方便的方法,不要指望它是“线程安全的”。我希望有更多关于这种方法的文档。

于 2013-01-24T08:17:41.817 回答
0

有时在 MRI 中实现线程安全代码是不值得的。因为大多数时候我们必须进行多进程部署。所以最简单的解决方案是数据库级别的唯一性验证。

class Person
  include Mongoid::Document
  field :ssn
  index({ ssn: 1 }, { unique: true })
end

所以当保存失败时回滚事务。请记住,模型级别的唯一性验证也容易出错。

于 2019-01-15T16:17:29.097 回答