Подтвердить что ты не робот

При каких обстоятельствах вы хотите, чтобы Rails был установлен НЕ для повторного подключения к MYSQL

Я испытываю несколько ошибок в приложении rails по строкам:

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

Что происходит, так это то, что соединение mysql закрывается после таймаута, а рельсы не замечают, пока он не станет слишком поздно.

средства защиты, которые я нахожу как представляется, для установки флаг reconnect в true в database.yaml или для любого действия с базой данных, добавляющего некоторый код:

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 кажется самым лучшим вариантом - но мне любопытно; почему вы не задали бы это значение по умолчанию в своей базе данных?

Я бы предпочел не решить одну проблему, вызвав нагрузку других дальше по строке.

Спасибо,

4b9b3361

Ответ 1

Как вы отметили в вопросе, один возможный побочный эффект автоматического повторного подключения (если он выполняется на уровне каждого оператора) заключается в том, что он не безопасен для транзакций.

Документация MySQL фактически указывает, что функция автоматического повторного подключения влияет на транзакции:

Любые активные транзакции откатываются, а режим автосохранения - reset.

Приложения, которые не написаны для этого, могут легко сломаться. В документации также перечислены некоторые другие побочные эффекты, вызванные функцией автоматического повторного подключения, все из которых могут привести к тому, что приложения не будут записаны, чтобы предвидеть, что поведение работает неправильно или не выполнено.

Кроме того, если соединение с базой данных будет внезапно потеряно, сервер может неправильно освободить блокировки, которые удерживаются соединением, поэтому в некоторых случаях приложение может заходить в тупик:

Если соединение падает, это возможно, что связанный сеанс с соединением на стороне сервера будет выполняться, если сервер еще не обнаружил, что клиент больше не подключен. В этом случае, любые блокировки, хранящиеся в оригинале соединение по-прежнему принадлежит к сеанс, поэтому вы можете его убить вызов mysql_kill().

Ответ 2

Из заметки о выпуске Rails 2.3 (выделено мной):

4.8 Повторное подключение соединений MySQL

MySQL поддерживает флаг повторного подключения в своих соединениях - если установлено значение true, клиент будет пытаться повторно подключиться к серверу, прежде чем отказаться от него в случае потерянного соединения. Теперь вы можете установить reconnect = true для своих соединений MySQL в database.yml, чтобы получить это поведение из приложения Rails. Значение по умолчанию - false, , поэтому поведение существующих приложений не изменяется.