Rails first_or_create中的竞争条件

我正试图在我的一个表字段中强制执行值的唯一性。 更改表格不是一种选择。 我需要使用ActiveRecord有条件地在表中插入一行,但我担心同步。

Rails ActiveRecord中的first_or_create是否first_or_create阻止竞争条件?

这是来自GitHub的first_or_create的源代码:

 def first_or_create(attributes = nil, options = {}, &block) first || create(attributes, options, &block) end 

由于多个进程的同步问题,重复条目是否可能导致数据库?

是的,这是可能的。

您可以显着降低与乐观或悲观锁定发生冲突的可能性。 当然,乐观锁定需要在表中添加一个字段,而悲观锁定也不能扩展 – 此外,它还取决于您的数据存储的function。

我不确定你是否需要额外的保护,但它是可用的。

find_or_create_by的Rails 4 文档提供了一个可能对此情况有用的提示:

请注意, 此方法不是primefaces的 ,它首先运行SELECT,如果没有结果,则尝试INSERT。 如果存在其他线程或进程,则两个调用之间存在竞争条件,并且最终可能会出现两个类似的记录。

这是否是一个问题取决于应用程序的逻辑,但在行具有UNIQUE约束的特定情况下,可能会引发exception,只需重试:

 begin CreditAccount.find_or_create_by(user_id: user.id) rescue ActiveRecord::RecordNotUnique retry end 

类似的错误捕获可能对Rails 3有用。(不确定在Rails 3中是否抛出相同的ActiveRecord::RecordNotUnique错误,因此您的实现可能需要不同。)