How to make ActiveRecord ThreadSafe

2019-01-23 20:34发布

How can I make the following controller threadsafe in rails 4 with postgresql:

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

I am running puma, so my concern is that if two threads run this controller at the same time, and a row doesn't exist with the specified value of column_name, two records will be created whereas I only want 1.

2条回答
我只想做你的唯一
2楼-- · 2019-01-23 20:44

Assume that threads have a 1:1 relationship with connections. So if you have 100 threads that need to access the database, you should crank the connection pool up to 100. If you have more worker threads than connections, you need to use a Queue (or some other thread safe data structure) to manage communication between them.

查看更多
爷、活的狠高调
3楼-- · 2019-01-23 21:06

Contrary to the comments, concurrent inserts on the same table are entirely permissible in PostgreSQL, so there's a race condition here.

To make this safe you must have a unique constraint (or primary key) on column_name. Duplicate inserts will then throw an exception which you can catch and retry with an update.

If you don't have a unique constraint, then you must LOCK TABLE ... IN EXCLUSIVE MODE to prevent concurrent upserts. Or use one of the concurrency-safe methods described in:

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

查看更多
登录 后发表回答