Je rencontre quelques erreurs sur une application de rails, le long des lignes de:Dans quelles circonstances vous voulez Rails à régler pas se reconnecter à MYSQL
ActiveRecord::StatementInvalid: Mysql::Error: Lost connection to MySQL server during query: SELECT * FROM `actions` WHERE (`foo`.`id` = 16)
Ce qui semble se produire est que MySQL la connexion est fermée après un délai d'expiration et les rails ne remarquent pas jusqu'à ce qu'il soit trop tard.
Le remedies I findappear to be pour définir le drapeau de rebranchement à true dans database.yaml, ou pour toute action de base de données en ajoutant quelques code comme ceci:
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
Je liste cette option over this one visible here, parce que cette option est apparemment peu sûr pour les transactions:
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
Parmi les options pour éviter cette erreur ennuyeux, l'option de rebranchement dans le fichier YAML semble par l'extrême l'option tidiest - mais je suis curieux; Pourquoi ne pas définir cette valeur par défaut dans votre base de données?
Je préfère ne pas résoudre un problème en causant une charge d'autres plus bas sur la ligne.
Merci,
Ok maintenant je suis totalement confus. Cela me suggère que la définition de 'reconnexion 'à' vrai' pourrait être nuisible, parce que les transactions qui sont annulées lorsqu'elles ne sont pas supposées sont une mauvaise chose. Quelle est la solution de contournement habituelle pour éviter cet état de choses? –
La solution consiste à s'assurer que vos transactions sont «atomiques», c'est-à-dire que si vous perdez la connexion et que vous vous reconnectez, toute la transaction doit être réessayée, pas seulement une seule déclaration dans la transaction. Je ne suis pas sûr comment cela fonctionne dans Rails, mais je suppose qu'une solution serait de mettre la transaction dans une procédure stockée - dans le code Rails, vous exécutez une seule instruction SQL pour exécuter la procédure stockée, puis si elle se reconnecte automatiquement , toute la transaction recommence depuis le début. –
OTOH, si vous n'utilisez pas de transactions, l'utilisation de la fonctionnalité de reconnexion automatique est probablement moins problématique. –