在SQLAlchemy中处理mysql重启

wRA*_*RAR 8 mysql error-handling pylons sqlalchemy

我的Pylons应用程序通过SQLAlchemy和python-MySQLdb使用本地MySQL服务器.当服务器重新启动时,打开的池连接显然已关闭,但应用程序不知道这一点,显然当它尝试使用这种连接时,它会收到"MySQL服务器已经消失":

File '/usr/lib/pymodules/python2.6/sqlalchemy/engine/default.py', line 277 in do_execute
  cursor.execute(statement, parameters)
File '/usr/lib/pymodules/python2.6/MySQLdb/cursors.py', line 166 in execute
  self.errorhandler(self, exc, value)
File '/usr/lib/pymodules/python2.6/MySQLdb/connections.py', line 35 in defaulterrorhandler
  raise errorclass, errorvalue
OperationalError: (OperationalError) (2006, 'MySQL server has gone away')
Run Code Online (Sandbox Code Playgroud)

此异常不会被捕获到任何地方,因此它会冒泡到用户.如果我应该在我的代码中的某处处理此异常,请在Pylons WSGI应用程序中显示此类代码的位置.或者SA本身可能有解决方案吗?

zif*_*fot 6

请参阅底部的EDIT以获取测试解决方案

我没试过,但也许使用PoolListener是一种方法吗?

你可以这样做:

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()])
Run Code Online (Sandbox Code Playgroud)

这样,每次从池中检出连接时,我们都会测试它是否实际连接到服务器.如果没有,我们给sqlalchemy一次机会重新连接.在那之后,如果问题仍然存在,我们放手.

PS:我没有测试这是否有效.

编辑:关于塔,修改发动机初始化上面显示将需要做your_app.model.init_model(塔0.9.7)或 your_app.config.environment.load_environment (塔1.0)功能- 这些都是这就是地方地方引擎实例被创建.

编辑

好.我能够重现描述的情况.上面的代码需要一些更改才能工作.以下是应该如何做的.无论是0.9.7还是1.0都没关系.

您需要编辑your_app/config/environment.py.将这些导出放在文件的顶部:

import sqlalchemy
import sqlalchemy.interfaces
import _mysql_exceptions
Run Code Online (Sandbox Code Playgroud)

load_environment函数的结尾应如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

这次我能够测试它(在Pylons 1.0 + SQLAlchemy 0.6.1上)并且它可以工作.:)