问题描述
如何使用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.
要确保安全,您必须具有列名
上的>唯一约束(或主键
)。然后,重复插入将引发异常,您可以捕获该异常并通过更新重试。
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:
这篇关于如何使ActiveRecord ThreadSafe的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!