2016-05-12 373 views
1

我有这个指标在我的模型的表:Rails的:ActiveRecord的:RecordNotUnique与first_or_create

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例外, 的问题是:

关键 “index_panel_us重复条目er_offer_visits_on_offer_id_and_panel_user_id”

我读过的轨道文件,让first_or_create!不是一个原子的方法,并可能导致这种问题在高并发环境和解决方案将只是捕捉异常,然后重试。

我尝试了不同的方法,包括Retriable gem重试一定次数来重复操作,但仍然引发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 

但代码仍然提高我所做的自定义异常,我真不明白它是如何失败的第一次尝试,因为创建记录记录存在,但当它试图找到记录时,它不会再找到它。

我错过了什么?

回答

0

您似乎在碰到rails查询缓存PanelUserOfferVisit.where(...).first查询:rails只是执行了相同的SQL查询,它认为结果在请求期间保持不变。

ActiveRecord::Base.connection.clear_query_cache前分贝第二个电话应该帮助

你也不必save!记录,如果它不是new_record?

0

如果我在这里正确理解你的问题是由于竞争状态。我没有发现的代码的确切一块从GitHub,但可以说的方法find_or_create是一样的东西(编辑:这里是the code):

def first_or_create!(attributes = nil, &block) 
    first || create!(attributes, &block) 
end 

你应该尝试使用optimisticpessimistic locking

解决竞争条件

一旦锁定在自定义方法中实现,您应该继续捕获可能的异常,但尝试清除缓存或使用之前的uncached块再次执行查找。

相关问题