如何使 ActiveRecord 线程安全 [英] How to make ActiveRecord ThreadSafe
问题描述
如何使用 postgresql 在 rails 4 中使以下控制器线程安全:
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
我正在运行 puma,所以我担心的是,如果两个线程同时运行此控制器,并且不存在具有 column_name 指定值的行,则会创建两条记录,而我只想要 1.
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.
推荐答案
与评论相反,在 PostgreSQL 中完全允许在同一个表上并发插入,因此这里存在竞争条件.
Contrary to the comments, concurrent inserts on the same table are entirely permissible in PostgreSQL, so there's a race condition here.
为了确保安全,您必须在 column_name
上有一个 unique
约束(或 primary key
).重复插入将引发异常,您可以捕获该异常并通过更新重试.
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.
如果您没有唯一约束,那么您必须LOCK TABLE ... IN EXCLUSIVE MODE
以防止并发更新插入.或者使用以下描述的并发安全方法之一:
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:
如何UPSERT(MERGE, INSERT ... ON DUPLICATE UPDATE) 在 PostgreSQL 中?
这篇关于如何使 ActiveRecord 线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!