我使用 Cherrypy 在 Python 3.2 之上构建了一个小的自定义 Web 框架来构建 WSGI 应用程序和 SQLAlchemy Core(仅用于连接池和执行文本 SQL 语句)。
我正在使用的版本:
- 蟒蛇:3.2.3
- 樱桃派:3.2.2
- SQL 炼金术:0.7.5
- Psycopg2:2.4.5
对于每个请求,使用sqlalchemy.engine.base.Engine
´sconnect
方法从池中检索数据库连接。请求处理程序完成后,使用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
´sclose
方法上设置了断点,但连接在到达此代码之前已关闭。这很奇怪。
我将不胜感激任何提示或帮助。
*编辑 * zzzeek 要求的信息:
“连接被关闭”的症状:很抱歉之前没有澄清这一点。它sqlalchemy.engine.Connection
是封闭的。
在处理程序中,我调用sqlalchemy.engine.base.Connection
´sexecute
方法从数据库中获取数据(选择语句)。我可以说它sqlalchemy.engine.Connection
是关闭的,因为我closed
在调用执行之前检查它的属性。
我可以在此处发布回溯,但您可能会在其中看到的唯一一件事是在我的 DB 包装器库中执行之前引发了异常(因为连接已关闭)。
如果我删除此检查(并让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.
我正在使用 pool_size = 5 的默认 SQLAlchemy 池类。
我知道当你没有实际代码时,你无法创造奇迹。但不幸的是,我不能分享它。是否有调试此类错误的最佳实践?还是唯一的选择是一步一步地更深入地调试并尝试弄清楚?
另一个观察:
当我在调试器(WingIDE)中启动服务器时,我无法显示错误。可能是因为调试器在解释代码时太慢了,以至于在处理第二个请求(RequestB)之前,连接以某种方式“修复”了。