Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Lidar com a reinicialização do mysql no SQLAlchemy


Observação de 2021: A resposta original é de 2010. Agora, a melhor abordagem, conforme apontado nos comentários, parece ser usar parâmetro pool_recycle .

A resposta original de 2010 segue.

Veja EDITAR na parte inferior da solução testada

Eu não tentei, mas talvez usando PoolListener é um caminho a percorrer?

Você poderia fazer algo assim:
class MyListener(sqlalchemy.interfaces.PoolListener):
    def __init__(self):
       self.retried = False
    def checkout(self, dbapi_con, con_record, con_proxy):
       try:
           dbapi_con.info() # is there any better way to simply check if connection to mysql is alive?
       except sqlalchemy.exc.OperationalError:
           if self.retried:
               self.retried = False
               raise # we do nothing
           self.retried = True
           raise sqlalchemy.exc.DisconnectionError

# next, code according to documentation linked above follows

e = create_engine("url://", listeners=[MyListener()])

Dessa forma, toda vez que a conexão estiver prestes a ser retirada do pool, testamos se ela está realmente conectada ao servidor. Caso contrário, damos ao sqlalchemy uma chance de se reconectar. Depois disso, se o problema ainda estiver lá, nós o deixamos ir.

PS:Eu não testei se isso funciona.

Edit:Quanto aos Pylons, as modificações na inicialização do mecanismo mostradas acima precisariam ser feitas em your_app.model.init_model (Pylons 0.9.7) ou your_app.config.environment.load_environment (Pylons 1.0) função - estes são estes são os lugares local onde a instância do mecanismo é criada.

EDITAR

Ok. Consegui reproduzir a situação descrita. O código acima precisa de algumas alterações para funcionar. Abaixo está como deve ser feito. Também não importa se é 0.9.7 ou 1.0.

Você precisa editar your_app/config/environment.py. Coloque essas exportações no topo do arquivo:
import sqlalchemy
import sqlalchemy.interfaces
import _mysql_exceptions

E o final da função load_environment deve ficar assim:
class MyListener(sqlalchemy.interfaces.PoolListener):
    def __init__(self):
       self.retried = False
    def checkout(self, dbapi_con, con_record, con_proxy):
       try:
           dbapi_con.cursor().execute('select now()')
       except _mysql_exceptions.OperationalError:
           if self.retried:
               self.retried = False
               raise
           self.retried = True
           raise sqlalchemy.exc.DisconnectionError

config['sqlalchemy.listeners'] = [MyListener()]

engine = engine_from_config(config, 'sqlalchemy.')
init_model(engine)

Desta vez consegui testá-lo (em Pylons 1.0 + SQLAlchemy 0.6.1) e funciona. :)