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