mysql - 在 SQLAlchemy 中处理 mysql 重启

标签 mysql error-handling sqlalchemy pylons

我的 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')

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

最佳答案

2021 注意:最初的答案来自 2010 年。现在,正如评论中指出的那样,更好的方法似乎是 using pool_recycle param .

2010 年的原始答案如下。


请参阅底部的 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()])

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

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

编辑:至于 Pylons,需要在 your_app.model.init_model (Pylons 0.9.7) 或 your_app.config.environment.load_environment < 中对上面显示的引擎初始化进行修改 < strike>(Pylons 1.0) 函数 - 这些是 这是创建引擎实例的地方

编辑

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

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

import sqlalchemy
import sqlalchemy.interfaces
import _mysql_exceptions

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)

这次我能够对其进行测试(在 Pylons 1.0 + SQLAlchemy 0.6.1 上)并且它有效。 :)

关于mysql - 在 SQLAlchemy 中处理 mysql 重启,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3033234/

相关文章:

php - 如何在连接表中搜索?

PHP、Mysql、Bootstrap 表不工作

c++ - boost spirit : Lex + Qi error reporting

php - 即使禁用 VERIFYPEER、VERIFYHOST 也会出现 SSL 连接错误

javascript - 以相同方式处理所有http错误

php - 如果花费的时间太长,则中止选择查询

mysql - Azure 虚拟机 - 无法访问 MySQL 数据库

python - assertRaises 没有捕捉到 IntegrityError ,Flask SQLAlchemy

python - 改组 SQLAlchemy 结果?

python - Scrapy + sqlalchemy + mysql错误