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

我在rails应用程序上遇到了一些错误,其中包括:

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

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

我找到的补救措施 似乎是在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 

我在此处列出了此选项,因为此选项显然对交易不安全:

 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?

我宁愿不通过引起其他人的进一步下线来解决一个问题。

谢谢,

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

MySQL 文档实际上明确指出自动重新连接function会影响事务:

回滚任何活动事务并重置自动提交模式。

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

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

如果连接断开,则如果服务器尚未检测到客户端不再连接,则与服务器端连接关联的会话可能仍在运行。 在这种情况下,原始连接所持有的任何锁仍然属于该会话,因此您可能希望通过调用mysql_kill()来终止它。

从Rails 2.3发行说明 (强调我的):

4.8重新连接MySQL连接

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