在什么情况下你希望Rails设置为不重新连接到MYSQL

时间:2009-10-08 16:21:07

标签: mysql ruby-on-rails

我在rails应用程序上遇到了一些错误,如下所示:

ActiveRecord::StatementInvalid: Mysql::Error: Lost connection to MySQL server during query: SELECT * FROM `actions` WHERE (`foo`.`id` = 16)

似乎正在发生的事情是mysql连接在超时后被关闭,并且rails没有注意到它为时已晚。

remedies I find appear to be在database.yaml中将reconnect标志设置为true,或者为任何数据库操作添加一些代码,如下所示:

def some_database_operation
  begin
    Account.find(1)
    # or some other database operations here...
  rescue ActiveRecord::StatementInvalid
    ActiveRecord::Base.connection.reconnect!
    unless @already_retried
      @already_retried = true
      retry 
    end
    raise
  else
    @already_retried = false
  end
end
end

我正在列出此选项over this one visible here,因为此选项显然对交易不安全:

ActiveRecord::ConnectionAdapters::MysqlAdapter.module_eval do
  def execute_with_retry_once(sql, name = nil)
    retried = false
    begin
      execute_without_retry_once(sql, name)
    rescue ActiveRecord::StatementInvalid => exception
      ActiveRecord::Base.logger.info "#{exception}, retried? #{retried}"

      # Our database connection has gone away, reconnect and retry this method
      reconnect!
      unless retried
        retried = true
        retry
      end
    end
  end

  alias_method_chain :execute, :retry_once
end

在避免这个恼人的错误的选项中,yaml文件中的重新连接选项似乎是最整洁的选项 - 但我很好奇;为什么你不会在数据库中默认将此值设置为true?

我宁愿不通过引起其他人的加载来解决一个问题。

谢谢,

2 个答案:

答案 0 :(得分:13)

正如您在问题中所指出的,自动重新连接的一个可能的副作用(如果在每个语句级别完成)是因为它不是事务安全的。

MySQL documentation实际上明确指出自动重新连接功能会影响事务:

  

回滚任何活动事务并自动提交模式   复位。

未编写处理此问题的应用程序很容易破解。该文档还列出了自动重新连接功能引起的许多其他副作用,所有这些都可能导致未写入的应用程序预期行为无法正常运行或失败。

此外,如果与数据库的连接突然丢失,服务器可能无法正确释放连接所持有的锁,因此听起来应用程序在某些情况下可能会死锁:

  

如果连接断开,则为   可能会话关联   与服务器端的连接   如果服务器仍将运行   尚未检测到客户端   已不再连接。在这种情况下,   原件持有的任何锁   连接仍然属于那个   会话,所以你可能想要杀死它   调用mysql_kill()。

答案 1 :(得分:6)

来自Rails 2.3 release notes(强调我的):

  

4.8重新连接MySQL连接

     

MySQL在其连接中支持重新连接标志 - 如果设置为true,则客户端将尝试重新连接到服务器,然后在连接丢失的情况下放弃。您现在可以在database.yml中为MySQL连接设置reconnect = true,以便从Rails应用程序中获取此行为。默认值为false,因此现有应用程序的行为不会更改。