如何使ActiveRecord线程安全

时间:2014-03-05 23:21:29

标签: ruby-on-rails postgresql ruby-on-rails-4 thread-safety rails-activerecord

如何使用postgresql在rails 4中使以下控制器线程安全:

def controller_action
  if Model.exists(column_name:"some_value")
  else
    @model=Model.new(column_name:"some_value")
    @model.save
  end
end

我正在运行puma,所以我担心的是如果两个线程同时运行此控制器,并且不存在具有指定值column_name的行,则将创建两个记录,而我只想要1. / p>

2 个答案:

答案 0 :(得分:13)

与注释相反,同一个表上的并发插入在PostgreSQL中是完全允许的,因此这里存在竞争条件。

为确保安全起见,您必须在unique上设置primary key约束(或column_name)。然后,重复插入将抛出异常,您可以捕获并重试更新。

如果您没有唯一约束,则必须LOCK TABLE ... IN EXCLUSIVE MODE以防止并发upsert。或者使用以下描述的并发安全方法之一:

How to UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) in PostgreSQL?

答案 1 :(得分:0)

假设线程与连接具有1:1的关系。因此,如果您有100个需要访问数据库的线程,则应该将连接池调高到100个。如果您有多个工作线程而不是连接,则需要使用Queue(或其他一些线程安全数据结构)来管理通信他们之间。