SQLAlchemy会话重新连接

2024-10-06 13:48:30 发布

您现在位置:Python中文网/ 问答频道 /正文

如果查询返回一个操作错误(如用户无权访问数据库或类似的内容),我如何强制引擎重新连接?

engine = create_engine(url, pool_recycle=3600)
Session = sessionmaker(bind=engine)

try:
      sesh = Session()
      sesh.query....
      sesh.close()
except OperationalError:
      # force engine to reconnect here somehow?

Tags: 用户引擎数据库url内容bindsession错误
3条回答

如果捕捉到指示连接在操作期间已关闭的错误,SQLAlchemy将在下次访问时自动重新连接。但是,当数据库断开连接时,您的事务就消失了,因此SQLAlchemy要求您在会话中发出rollback(),以便在应用程序中建立一个新事务将要发生。然后你需要重新开始你的整个交易。

处理这个问题有几个角度。您应该通读文档的Dealing with Disconnects部分,其中说明了使用断开连接的两种方法。除此之外,如果你真的想从你离开的地方接你的交易,你需要“重播”整个事情,假设你在你的交易中做了不止一件事。这最适合于应用程序代码,它将需要执行的操作打包到一个可以再次调用的函数中。请注意,SQLAlchemy的未来版本可能会引入一个名为事务重放扩展的扩展,它提供了另一种方法来实现这一点,但是它会有很多警告,因为以通用方式重放丢失的事务并不是一件小事。

自从这个问题第一次被回答以来,发生了很多事情。

通过采用一种悲观的错误处理方法,您可以获得最棒的bug实现,而且非常有效。

创建引擎时应用pool_pre_ping=True,如下所示:

engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)

查看更多信息:docs.sqlalchemy.org/en/latest/core/pooling.html#pool-disconnects-pessimistic


另一种方法是以乐观的方式处理错误-当错误发生时。在这种情况下,可以在try-and-except中包装execute语句,如果引发异常,则使连接无效。一旦连接失效,您就可以重新实例化它。

查看更多信息:docs.sqlalchemy.org/en/latest/core/pooling.html#disconnect-handling-optimistic


这两种方法都适用于连接超时的情况,例如过夜/周末。它还使It操作更容易关闭数据库,并且不必太担心依赖重启的下游应用程序。如果您处理非常关键的事务,那么考虑安全事务处理(如zzzeek所述)是非常有价值的。

如果在烧瓶中使用sqlalchemy,当您查询

MyModel.query.all()

你会犯错误,比如

  File "./lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 427, in _revalidate_connection
    "Can't reconnect until invalid "
StatementError: (sqlalchemy.exc.InvalidRequestError) Can't reconnect until invalid transaction is rolled back

您只需通过

MyModel.query.session.close()
MyModel.query.all()

相关问题 更多 >