Ruby on rails Rails:ActiveRecord:RecordNotUnique与第一个\u或\u创建
我的模型表中有以下索引:Ruby on rails Rails:ActiveRecord:RecordNotUnique与第一个\u或\u创建,ruby-on-rails,concurrency,Ruby On Rails,Concurrency,我的模型表中有以下索引: UNIQUE KEY `index_panel_user_offer_visits_on_offer_id_and_panel_user_id` (`offer_id`,`panel_user_id`) 该代码: def get_offer_visit(offer_id, panel_user_id) PanelUserOfferVisit.where(:offer_id => offer_id, :panel_user_id => panel_use
UNIQUE KEY `index_panel_user_offer_visits_on_offer_id_and_panel_user_id` (`offer_id`,`panel_user_id`)
该代码:
def get_offer_visit(offer_id, panel_user_id)
PanelUserOfferVisit.where(:offer_id => offer_id, :panel_user_id => panel_user_id).first_or_create!
end
在应用程序中随机导致ActiveRecord::RecordNotUnique异常,
问题是:
钥匙的重复输入
'索引\u面板\u用户\u报价\u访问\u报价\u id\u和\u面板\u用户\u id'
我在rails上读到了first\u或\u create
不是一种原子方法,在高并发性环境中可能会导致此类问题,解决方案只是捕获异常并重试
我尝试了不同的方法,包括重试一定次数以重复该操作,但仍然引发RecordNotUnique
我甚至试图改变逻辑:
def get_offer_visit(offer_id, panel_user_id)
begin
offer_visit = PanelUserOfferVisit.where(:offer_id => offer_id, :panel_user_id => panel_user_id).first_or_initialize
offer_visit.save!
offer_visit
rescue ActiveRecord::RecordNotUnique
offer_visit = PanelUserOfferVisit.where(:offer_id => offer_id, :panel_user_id => panel_user_id).first
raise Exception.new("offer_visit not found") if offer_visit.nil?
offer_visit
end
end
但是代码仍然引发了我所做的自定义异常,我真的不明白为什么它在第一次尝试时无法创建记录,因为该记录存在,但当它尝试查找该记录时,却无法再次找到它
我遗漏了什么?您似乎正在为
PanelUserOfferVisit访问rails查询缓存。其中(…)。首先,rails刚刚执行了相同的SQL查询,它认为在请求期间结果将保持不变
ActiveRecord::Base.connection.clear\u query\u cache
在第二次调用db之前应该会有所帮助
您也不必保存代码>如果不是新记录,则记录?
如果我正确理解,您的问题是由于比赛条件造成的。我没有从Github中找到确切的代码片段,但假设方法find\u或\u create
类似于(编辑:这里是):
您应该尝试使用或解决比赛条件
在自定义方法中实现锁定后,应继续捕获可能的NotUnique
异常,但在再次执行查找之前,请尝试清除缓存或使用uncached
块 我也遇到过类似的问题,但根本原因与种族状况无关
使用first\u或\u create代码>,插入删除值中的周围空格,但选择不删除
因此,如果您尝试以下方法:
Users.where(email: 'user@mail.com ')
(注意字符串末尾的空格),生成的sql查询将是:
SELECT "users".* FROM "users" WHERE "users"."email" = 'user@mail.com ' ORDER BY "users"."id";
INSERT INTO "users" ("email") VALUES ('user@mail.com');
这将导致找不到可能存在的记录,那么插入查询将是:
SELECT "users".* FROM "users" WHERE "users"."email" = 'user@mail.com ' ORDER BY "users"."id";
INSERT INTO "users" ("email") VALUES ('user@mail.com');
如果记录具有以下内容,则会导致ActiveRecord::RecordNotUnique
错误user@mail.com'因为电子邮件已经存在
关于你的问题,我没有足够的细节,所以这可能是无关的,但它可能会帮助其他人