2014-12-02 103 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

相关问题