Python SQLAlchemy - “MySQL server has gone away”
Permet d'avoir un regard sur le prochain extrait -
@event.listens_for(Pool, "checkout")
def check_connection(dbapi_con, con_record, con_proxy):
cursor = dbapi_con.cursor()
try:
cursor.execute("SELECT 1") # could also be dbapi_con.ping(),
# not sure what is better
except exc.OperationalError, ex:
if ex.args[0] in (2006, # MySQL server has gone away
2013, # Lost connection to MySQL server during query
2055): # Lost connection to MySQL server at '%s', system error: %d
# caught by pool, which will retry with a new connection
raise exc.DisconnectionError()
else:
raise
engine = create_engine('mysql://user:[email protected]/dbname', pool_recycle = 3600,pool_size=10, listeners=[check_connection])
session_factory = sessionmaker(bind = engine, autoflush=True, autocommit=False)
db_session = session_factory()
...
some code that may take several hours to run
...
db_session.execute('SELECT * FROM ' + P_TABLE + " WHERE id = '%s'" % id)
Je pensais que l'enregistrement de la checkout_connection fonction en vertu de la caisse de l'événement permettrait de résoudre le problème, mais il na pas
maintenant, la question est de savoir comment je suis supposé dire SQLAlchemy poignée de connexion, des décrocheurs, de sorte que chaque fois que j'appelle execute (), il va vérifier si la connexion est disponible et si non, il va lancer une fois de plus?
----Mise à JOUR----
La version de SQLAlchemy est 0.7.4
----Mise à JOUR----
def checkout_listener(dbapi_con, con_record, con_proxy):
try:
try:
dbapi_con.ping(False)
except TypeError:
dbapi_con.ping()
except dbapi_con.OperationalError as exc:
if exc.args[0] in (2006, 2013, 2014, 2045, 2055):
raise DisconnectionError()
else:
raise
engine = create_engine(CONNECTION_URI, pool_recycle = 3600,pool_size=10)
event.listen(engine, 'checkout', checkout_listener)
session_factory = sessionmaker(bind = engine, autoflush=True, autocommit=False)
db_session = session_factory()
session_factory est envoyée à chaque nouvellement créé fil
class IncidentProcessor(threading.Thread):
def __init__(self, queue, session_factory):
if not isinstance(queue, Queue.Queue):
raise TypeError, "first argument should be of %s" (type(Queue.Queue))
self.queue = queue
self.db_session = scoped_session(session_factory)
threading.Thread.__init__(self)
def run(self):
self.db_session().execute('SELECT * FROM ...')
...
some code that takes alot of time
...
self.db_session().execute('SELECT * FROM ...')
maintenant, quand exécuter court après une grande période de temps-je obtenir le "MySQL server has gone away" erreur
- Avez-vous vérifier si caisse événement est déclenché? Aussi avez-vous décorer votre fonction check_connection avec @événement.listens_for(Piscine, "la caisse")? Ce lien peut être utile docs.sqlalchemy.org/en/latest/core/...
- ah oui j'ai oublié d'ajouter le décorateur maintenant, il semble qu'il essaie d'utiliser la fonction mais ses déclenche une exception en disant: - "ne pas mettre en œuvre de: first_connect, l'archivage, l'extraction, l'connecter"
- Quelle est la version de sqlalchemy utilisez-vous? Aussi pourriez-vous poster le fichier de code avec le décorateur ici?
- J'ai mis à jour le code source, et la version de sqlalchemy est 0.7.4
- Supprimer les auditeurs=[check_connection] mot-clé le paramètre de create_engine appel. Il n'est pas nécessaire maintenant que vous avez un décorateur qui raconte sqlalchemy que check_connection est un écouteur. C'est la raison pour laquelle il s'attend de la mise en œuvre de l'un de ces "first_connect, l'archivage, l'extraction, l'connecter"
- ok ça marche, je vous tiendrai au courant ici dans un cas, il sera effectivement surmonter le "mysql server has gone away" erreur et merci beaucoup!!
- Qu'avez-vous changé pour tout le travail? J'ai exactement le même problème (les connections après une longue période d'inactivité). Seriez-vous prêt à poster "résumé" de votre solution?
Vous devez vous connecter pour publier un commentaire.
Il y avait un parler de ce sujet, et ce doc décrit le problème plutôt bien, j'ai donc utilisé leur approche recommandée pour traiter ces erreurs: http://discorporate.us/jek/talks/SQLAlchemy-EuroPython2010.pdf
Il ressemble à quelque chose comme ceci:
self.db_session.execute
ping()
appels, et si les deux échoue, une exception est levée. Est-il un moyen (du sens) pour essayer de créer une nouvelle connexion, au lieu de lever? Ou est le ping suffisante pour rétablir de nouvelles connexions si elles ont expiré?ping()
. L'ajout d'une autre exception (except AttributeError: return
) a résolu mon problème. Peut aider quelqu'un d'autre.Essayer le
pool_recycle
argumentcreate_engine
.De la documentation:
Vous pouvez essayer quelque chose comme ceci:
Si la connexion a s'en aller, ce qui permettra de constituer une exception, la session sera
rollback
d, il va essayer de nouveau est susceptible de réussir.