2016-05-12 283 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塊再次執行查找。

相關問題