gpt4 book ai didi

ruby-on-rails - find_or_create ActiveRecord::RecordNotUnique 救援重试不起作用

转载 作者:数据小太阳 更新时间:2023-10-29 07:19:42 24 4
gpt4 key购买 nike

使用 ruby​​ 2.1.2 和 rails 4.1.4。我对数据库中的电子邮件列有唯一约束。如果存在一个线程正在创建用户而另一个线程试图同时创建的竞争条件,则会引发记录不唯一的异常。我正在尝试通过重试来处理此异常,以便在重试时它将在 find_or_create 的 SELECT 期间找到客户。

然而,它似乎并没有起作用。它用尽重试次数,然后重新引发异常。

这是我最初做的:

retries = 10
begin
user = User.find_or_create_by(:email => email)
rescue ActiveRecord::RecordNotUnique
retry unless (retries-=1).zero?
raise
end

然后我想也许数据库连接正在缓存 SELECT 查询结果,导致它认为用户仍然不存在并继续尝试创建它。为了解决这个问题,我尝试使用 Model.uncached 来禁用查询缓存:

retries = 10
begin
User.uncached do
user = User.find_or_create_by(:email => email)
end
rescue ActiveRecord::RecordNotUnique
retry unless (retries-=1).zero?
raise
end

`

这也行不通。我不确定还能做什么来解决这个问题?我应该增加重试次数吗?在重试之间添加 sleep 延迟?有没有更好的方法来清除查询缓存(如果这是问题所在?)

有什么想法吗?

谢谢!

最佳答案

如果您使用的是 Postgres,则有一个 upsert ( https://github.com/jesjos/active_record_upsert) gem 可以很容易地在这样的场景中添加“ON CONFLICT DO NOTHING/UPDATE”。您可以将您的代码替换为

User.upsert(email: email)

如果您想在同一操作中添加或更新其他数据作为同一更新插入调用的一部分,您应该首先指定电子邮件是该模型的唯一键:

class User < ActiveRecord::Base
upsert_keys [:email]
end

编辑:要确定您的方法存在的问题,请尝试发布日志的相关部分,我们可以在其中查看发出了哪些 SQL 语句,包括事务 BEGIN/COMMIT。

关于ruby-on-rails - find_or_create ActiveRecord::RecordNotUnique 救援重试不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41051361/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com