最近,我在我的应用程序中发现了很多死锁错误。
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
我没有找到根本原因,谁能给我一些建议?提前致谢!!!
最佳答案
我的猜测是您正在使用 InnoDB 并且可能正在执行并发插入。
要追踪和了解原因,请查看这些文章:
- MySQL deadlocks with concurrent inserts
- How can I configure MySQL Innodb to handle 1000s of inserts per hour?
解决该问题的一种方法是重试,如下面的代码所示:
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
或者,有一些 gem ,如 transaction_retry处理 MySQL 死锁。
关于Mysql2::错误:尝试获取锁时发现死锁;尝试重新启动事务:INSERT INTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27246003/