【问题标题】:SQLAlchemy Core: Connection is closing unexpectedlySQLAlchemy Core:连接意外关闭
【发布时间】:2012-08-21 11:45:47
【问题描述】:

我在 Python 3.2 之上构建了一个小的自定义 Web 框架,使用 Cherrypy 来构建 WSGI 应用程序和 SQLAlchemy Core(仅用于连接池和执行文本 SQL 语句)。

我正在使用的版本:

  • Python:3.2.3
  • CherryPy:3.2.2
  • SQL 炼金术:0.7.5
  • Psycopg2:2.4.5

对于每个请求,使用sqlalchemy.engine.base.Engine´s connect 方法从池中检索数据库连接。请求处理程序完成后,使用close 方法关闭连接。伪代码举例:

with db.connect() as db:
    handler(db)

db.connect() 是这样定义的上下文管理器:

@contextmanager
def connect(self):
    conn = self.engine.connect()
    try: 
        yield conn
    finally:
        conn.close()

我希望这是执行此任务的正确做法。它一直有效,直到页面处理程序变得更加复杂。

我的行为很奇怪。由于未知原因,连接有时会在处理程序完成工作之前关闭。但不是每次!

通过观察,这仅在连续快速发出请求时才会发生。如果我在请求之间稍作停顿,则连接不会关闭并且请求成功完成。但无论如何,这种情况并非每次都会发生。我在请求的失败/成功中没有找到更具体的模式。

我观察到连接没有被我的上下文管理器关闭。那时它已经关闭了。

我的问题: 如何确定我的连接何时、为什么以及通过什么代码关闭?

我尝试调试。我在sqlalchemy.engine.base.Connection´s close 方法上设置了断点,但连接在到达此代码之前已关闭。这很奇怪。

我将不胜感激任何提示或帮助。

*编辑 * zzzeek 要求的信息:

“连接被关闭”的症状: 很抱歉之前没有澄清这一点。关闭的是sqlalchemy.engine.Connection

在处理程序中,我调用sqlalchemy.engine.base.Connection´s execute 方法从数据库中获取数据(选择语句)。我可以说sqlalchemy.engine.Connection 已关闭,因为我在调用执行之前检查它的closed 属性。

我可以在此处发布回溯,但您可能会在其中看到的唯一一件事是在我的数据库包装器库中执行之前引发了异常(因为连接已关闭)。

如果我删除此检查(并让execute 方法执行),SQLAlchemy 会引发此异常:http://pastebin.com/H6052yca

关于 zzzeek 提到的并发问题。我必须道歉。经过更多观察,情况略有不同。

这是如何调用错误的确切过程:

Request for HandlerA. Everything ok. 
Wait moment (about 10-20s).
Request for HandlerB. Everything ok.

Request for HandlerA. Everything ok.
Immediate request for HandlerB. Error!
Immediate request for HandlerB. Error!
Immediate request for HandlerB. Error!
Wait moment (about 10-20s).
Request for HandlerB. Everything ok.

我使用默认的 SQLAlchemy 池类,pool_size = 5。

我知道,如果您没有实际代码,就无法创造奇迹。但不幸的是,我不能分享它。是否有调试此类错误的最佳实践?还是唯一的选择是一步一步地更深入地调试并尝试弄清楚?

另一个观察结果:

当我在调试器 (WingIDE) 中启动服务器时,我无法显示错误。可能是因为调试器在解释代码时太慢了,以至于在处理第二个请求 (RequestB) 之前,连接就以某种方式“修复”了。

【问题讨论】:

  • 您是否尝试过使用 create_engine 函数的参数 echo=True(用于 sqlalchemy 的详细输出)?
  • 我间接使用它。我将记录器sqlalchemy.enginesqlalchemy.pool 保存到磁盘上的日志文件中。记录器处理程序设置为调试级别。而且根据日志文件,里面并没有发生任何意外。我应该在某处为您发布日志文件吗?我不确定他们是否能以某种方式提供帮助。也许我也应该尝试保存sqlalchemy.dialect 日志。
  • 好的,sqlalchemy.dialects 记录器为空。 sqlalchemy.enginesqlalchemy.pool 记录器中的任何内容都没有暗示任何不好的事情。
  • “连接被关闭”的症状是什么?什么是堆栈跟踪 + 异常消息 + 显示它“关闭”的确切代码?这里不清楚它是“关闭”的 sqlalchemy.engine.Connection 还是底层 DBAPI 连接。该问题还表明存在并发问题,因为它仅在多个快速请求时发生。正在使用的池类型可能与“处理程序”对该连接所做的事情有关。
  • @zzzeek 您好,感谢您的回复!我编辑了问题,添加了请求的信息。

标签: python python-3.x sqlalchemy database-connection


【解决方案1】:

经过一天的调试。我发现了问题。

不幸的是,它与 SQLAlchemy 没有直接关系。所以这个问题应该被删除。但是你们试图帮助我,所以我会回答我自己的问题。也许有一天,有人会发现这很有帮助。

基本上,错误是由我的自定义发布/订阅方法引起的,这些方法在多线程环境中不能很好地发挥作用。

我尝试逐行执行代码...这不起作用(正如我在问题中描述的那样)。所以我开始生成非常详细的日志记录正在发生的事情。

即便如此,一切看起来都很正常,直到我注意到崩溃前的几行,模型中引用的 Connection 对象的地址发生了变化。这实际上意味着将另一个 Connection 对象分配给模型,并且该连接对象已经关闭。

所以教训是。当一切看起来正确时,打印/记录有问题的对象的 repr()。

感谢评论者的宝贵时间。

【讨论】:

    猜你喜欢
    • 2020-12-23
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多