有一些方法:first_or_create_by
,find_or_create_by
等,其工作原理如下:
显然,这些方法的并发调用可能让两个线程都找不到他们想要的东西,而在第3步,一个人会意外地失败。
似乎更好的解决方案是,
create_or_find
那是:
那么在什么情况下我想使用Rails内置的东西而不是我自己的(看似更可靠)create_or_find
?
答案 0 :(得分:9)
在深入研究之后,我将回答我自己的问题。
查找或创建的文档说:
请注意此方法不是原子的,它先运行一个SELECT,然后运行 如果没有结果,则尝试INSERT。如果还有其他 线程或进程在两个调用之间存在竞争条件 可能是你最终得到两个类似的记录。
这是否是一个问题取决于的逻辑 应用程序,但在行具有UNIQUE的特定情况下 约束可能会引发异常,只需重试:
begin CreditAccount.find_or_create_by(user_id: user.id) rescue ActiveRecord::RecordNotUnique retry end
这通常会比create_or_find
具有更好的性能。
考虑到create_or_find
在成功的情况下需要1个DB旅行,每个唯一记录只会发生一次。每隔一次需要2次DB跳转(创建和搜索失败)。
重试find_or_create
将在失败的情况下需要3次旅行(搜索,失败创建,再次搜索),但这只能在非常小的窗口中发生这么多次。除此之外,每隔一次调用将find_or_create
一条记录,将需要1次DB旅行。
因此,重试find_or_create
的摊销成本更好,并且很快就达到了。
答案 1 :(得分:0)
显然,默认情况下它不是线程安全的,但它们可以通过这种方式设计,以便更好地运行。
如果有必要,可以更快地找到并创建大部分时间的失败创建,有时可以避免异常(可以处理)。
此discussion可能对您有所帮助。