【问题标题】:Rails 2.3 - Handling ActiveRecord::StatementInvalid within the modelRails 2.3 - 在模型中处理 ActiveRecord::StatementInvalid
【发布时间】:2013-01-19 09:06:10
【问题描述】:

我的 Rails 应用程序中的一个模型开始抛出 ActiveRecord::StatementInvalid 并显示以下消息:“Mysql::Error: Deadlock found when trying to get lock; try restarting transaction ...” 我一开始处理这个问题的方式是有:

myModel.update/save/update_all

我将它包装起来以捕获该异常,例如:

begin
  myModel.update_all(..) 
rescue Exception => e
  if e.message.include?("Deadlock")
    retry
  end
end

这样做的问题是,我必须在有更新/保存的任何地方挽救这个异常,并且我必须小心重试确实会做两次事情,甚至更糟的是进入无限循环。我可以在模型级别的一个位置(例如在回调中)解决此问题吗?似乎 after_save 或 after_update 不会起作用,因为此时还没有抛出异常。我在 Rails 2.3.8 中,所以 after_commit 或 after_rollback 对我来说不是一个选项。有任何想法吗?谢谢! p.s:我知道有一些方法可以避免或减少 mysql 出现死锁的机会,但我可以在死锁发生后重新启动事务,因为在我的情况下,死锁不会经常发生

【问题讨论】:

  • 特别是如果有一种方法可以执行 mysql 建议的操作:“尝试重新启动事务”。也许覆盖我模型的保存和更新方法?

标签: ruby-on-rails ruby callback deadlock


【解决方案1】:

也许您可以在 ApplicationController 中尝试“rescue_from”,如下所示:

class ApplicationController < ActionController::Base

    rescue_from ActiveRecord::StatementInvalid, :with => :my_custom_error_handler


    protected

    def my_custom_error_handler(exception)
      ...
    end
end

但我不确定它是否能正确处理您的重试。值得一试。告诉我!

【讨论】:

  • 好主意。正如你所说,问题是如何处理它。一个想法可能是重新提交 mysql 语句,因为它包含在异常消息中,所以它实际上看起来像“Mysql::Error: Deadlock found when trying to get lock; try restarting transaction: UPDATE XXX SET YYY WHERE ZZZ) 所以我可以解析异常消息以找到 mysql 语句并重新提交它,但我不确定这是否是最干净的解决方案:)
【解决方案2】:

我想我会用这个 gem 来解决死锁问题 https://github.com/mperham/deadlock_retry

【讨论】:

    猜你喜欢
    • 2013-10-31
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 2013-06-07
    • 2017-02-13
    相关资源
    最近更新 更多