2014-12-02 101 views
5

最近,我在我的應用程序中發現了很多死鎖錯誤。Mysql2 ::錯誤:嘗試獲取鎖時發現死鎖;嘗試重新啓動事務:INSERT INTO

Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `products`.... 

的代碼如下:用戶已經創建

後,我將一些產品添加到用戶。我不明白爲什麼會發生僵局。

class User < ActiveRecord::Base 
    after_create :add_products 
    has_many :products, :dependent => :destroy 

    def self.create_user 
     User.create!(.......) 
    end 

    def add_products 
     Product.add(self, "product_name", 10) 
    end 
    ..... 
end 

class Product < ActiveRecord::Base 
    belongs_to :user 

    def self.add(user, product_name, amount) 
     transaction do 
     product = user.products.find_by_product_name(product_name) 
     if product 
      product.increment :amount, amount 
      product.save! 
     else 
      product = self.create! user_id: user.id, 
            product_name: product_name, 
            amount: amount 
     end 
     end 
     product 
    end 
end 

我沒有找到根本原因,任何人都可以給我一些建議嗎?提前致謝!!!

+0

隨着add方法,你爲什麼要再次使用的自我?改用產品。 – Jyothu 2014-12-02 09:41:32

+0

你說得對,我已經修改過。 – pangpang 2014-12-02 09:54:08

+0

請參考下面的鏈接,這將幫助你 http://stackoverflow.com/questions/2332768/how-to-avoid-mysql-deadlock-found-when-trying-to-get-lock-try-重新啓動-tra – Sush 2014-12-02 10:20:45

回答

9

我的猜測是你正在使用InnoDB,並且可能在併發插入。

要跟蹤和了解引起結帳這些文章

一種方法是重試,如下面的代碼

def add_products 
    retries = 0 

    begin 
     Product.add(self, "product_name", 10) 
    rescue ActiveRecord::StatementInvalid => ex 
     if ex.message =~ /Deadlock found when trying to get lock/ #ex not e!! 
      retries += 1 
      raise ex if retries > 3 ## max 3 retries 
      sleep 10 
      retry 
     else 
      raise ex 
     end 
    end 
end 

或者像transaction_query這樣的寶石可以處理MySQL死鎖。

+0

我有一個問題:保存和創建方法被封裝在一個事務中,是否需要添加事務到'添加'方法? – pangpang 2014-12-03 02:38:48

+0

如果您有多個插入以確保全部成功或中止,則交易是必需的。完全取決於你的實現,但只要看看你提供的代碼,我會說沒有必要。 – shiva 2014-12-03 03:34:32

2

這節省了我很多頭痛:transaction_retry紅寶石寶石。

從寶石的自述:

Retries database transaction on deadlock and transaction serialization errors. Supports MySQL, PostgreSQL, and SQLite.

+1

對不起,我知道你在這個網站上有很高的聲譽,但是......這個答案只是一種鏈接而不是垃圾郵件。如果你可以更多地瞭解這將如何幫助解決這個問題,我們將不勝感激 – iGbanam 2016-03-16 09:32:59

+0

@Yasky這是一個精確處理問題所要求的問題的寶石。在併發環境中,有時死鎖是不可避免的,唯一的辦法就是重試交易。這寶石,這項工作自動。 – fguillen 2016-03-16 09:51:53

相關問題