Python SQLAlchemy连接错误
我遇到了一些奇怪的bug,这些bug似乎是由Sqlalchemy使用的连接引起的,我无法准确地确定。。我希望有人知道这里发生了什么 我们正在开发一个金字塔(版本1.5b1),并将Sqlalchemy(版本0.9.6)用于所有数据库连接。有时我们会收到与db连接或会话相关的错误,大多数情况下这可能是Python SQLAlchemy连接错误,python,multithreading,sqlalchemy,Python,Multithreading,Sqlalchemy,我遇到了一些奇怪的bug,这些bug似乎是由Sqlalchemy使用的连接引起的,我无法准确地确定。。我希望有人知道这里发生了什么 我们正在开发一个金字塔(版本1.5b1),并将Sqlalchemy(版本0.9.6)用于所有数据库连接。有时我们会收到与db连接或会话相关的错误,大多数情况下这可能是光标已关闭或此连接已关闭错误,但我们也会收到其他相关异常: (OperationalError) connection pointer is NULL (InterfaceError) cursor a
光标已关闭
或此连接已关闭
错误,但我们也会收到其他相关异常:
(OperationalError) connection pointer is NULL
(InterfaceError) cursor already closed
Parent instance <...> is not bound to a Session, and no contextual session is established; lazy load operation of attribute '...' cannot proceed
A conflicting state is already present in the identity map for key (<class '...'>, (1001L,))
This Connection is closed (original cause: ResourceClosedError: This Connection is closed)
(InterfaceError) cursor already closed
Parent instance <...> is not bound to a Session; lazy load operation of attribute '...' cannot proceed
Parent instance <...> is not bound to a Session, and no contextual session is established; lazy load operation of attribute '...' cannot proceed
'NoneType' object has no attribute 'twophase'
(OperationalError) connection pointer is NULL
This session is in 'prepared' state; no further
- 我们的所有orm对象都有一个基本模型: BaseModel=declarative_base(cls=BaseModelObj,metaclass=BaseMeta,metadata=db_meta)
- 我们使用pyramid_tm tween来处理请求期间的事务
- 我们将db_session.remove()挂接到pyramid NewResponse事件(在一切运行之后触发)。我还试着把它放在一个单独的二人组中,在pyramid_tm之后运行,甚至根本不做,这些似乎都没有效果,所以响应事件似乎是放置它的最干净的地方
- 我们在金字塔项目的主入口点创建引擎,并使用空池,将连接池留给pgbouncer。我们还在此处为BaseModel配置会话和绑定: engine=engine\u from_config(config.registry.settings,'sqlalchemy',poolclass=NullPool) db\u session.configure(bind=engine,query\u cls=FilterQuery) BaseModel.metadata.bind=引擎 config.add_订阅服务器(清理\u db_会话,NewResponse) return config.make_wsgi_app()
- 在我们的应用程序中,我们使用以下方式访问所有数据库操作: 从project.db导入db_会话 ... db_session.query(MyModel).filter(…) db_session.execute(…)
- 我们使用psycopg2==2.5.2来处理到postgres的连接,pgbouncer介于两者之间
- 我确保对db_会话或连接的引用不会保存在任何地方(这可能会导致其他线程重用它们)
@event.listens_for(Engine, "before_cursor_execute")
def _before_cursor_execute(conn, cursor, stmt, params, context, execmany):
conn.pdtb_start_timer = time.time()
@event.listens_for(Engine, "after_cursor_execute")
def _after_cursor_execute(conn, cursor, stmt, params, context, execmany):
print conn.pdtb_start_timer
令人惊讶的是,这有时会引发异常:“Connection”对象没有属性“pdtb\u start\u timer”
这让我觉得很奇怪。。我发现了一个类似的讨论:
并尝试将strategy='threadlocal'添加到引擎中,据我所知,这将强制踏板连接1。但是这对我看到的错误没有任何影响。。(除了一些单元测试失败之外,因为我需要两个不同的会话/连接来进行一些测试,这将强制关联1个连接)
有没有人知道这里会发生什么,或者对如何解决这个问题有更多的建议
提前谢谢
Matthijs Blaas更新:多个命令在一条准备好的sql语句中发送所导致的错误。Psycopg2似乎允许这样做,但显然它会导致奇怪的问题。PG8000连接器对多个命令要求更严格,发送一个命令解决了问题 我有一个关于这个问题的更新,现在我只在gevent模式下使用gunicorn,一致地得到“(InterfaceError)游标已关闭”异常:
@event.listens_for(Engine, "before_cursor_execute")
def _before_cursor_execute(conn, cursor, stmt, params, context, execmany):
conn.pdtb_start_timer = time.time()
@event.listens_for(Engine, "after_cursor_execute")
def _after_cursor_execute(conn, cursor, stmt, params, context, execmany):
print conn.pdtb_start_timer