mam przeżywa kilka błędów aplikacji na szynach, wzdłuż linii:W jakich okolicznościach chcesz Szyny należy ustawić NIE ponownie połączyć się z MySQL
ActiveRecord::StatementInvalid: Mysql::Error: Lost connection to MySQL server during query: SELECT * FROM `actions` WHERE (`foo`.`id` = 16)
Co wydaje się dzieje, że mysql połączenie jest zamykane po przekroczeniu limitu czasu, a szyny nie zauważają, dopóki nie jest za późno.
remedies I findappear to be ustawić flagę ponownie połączyć się z prawdą w database.yaml lub do jakiegokolwiek działania bazy dodanie kodu tak:
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
Jestem wymieniając tę opcję over this one visible here, ponieważ opcja ta jest najwyraźniej niebezpieczne dla transakcji:
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
z opcji, aby uniknąć ten przykry błąd, opcja reconnect w pliku YAML wydaje przez zdecydowanie tidiest opcji - ale jestem ciekawy; dlaczego nie ustawisz domyślnie tej wartości w bazie danych?
Wolę nie rozwiązywać jednego problemu, powodując obciążenie innych w dalszej linii.
Dzięki,
OK, teraz jestem całkowicie zdezorientowany. To sugeruje, że ustawienie 'reconnect' na' true' może być szkodliwe, ponieważ transakcje wycofywane, gdy nie są przypuszczane, brzmią jak coś złego. Jakie jest zwykle obejście, aby uniknąć tego stanu rzeczy? –
Rozwiązaniem jest upewnienie się, że twoje transakcje są "atomowe" - to znaczy, że w przypadku utraty połączenia i ponownego połączenia, cała transakcja powinna zostać ponowiona, a nie tylko pojedyncze oświadczenie w ramach transakcji. Nie jestem pewien, jak to działa w Railsach, ale myślę, że jednym z rozwiązań byłoby umieszczenie transakcji w procedurze przechowywanej - w kodzie Railsowym wykonuje się pojedynczą instrukcję SQL, aby uruchomić procedurę przechowywaną, a następnie, jeśli automatycznie się ponownie łączy. , cała transakcja zaczyna się od początku. –
OTOH, jeśli nie korzystasz z transakcji, użycie funkcji automatycznego ponownego nawiązywania połączenia jest prawdopodobnie mniejszym problemem. –