SQLAlchemy会话重新连接

bwb*_*ing 6 python sqlalchemy

如果查询返回操作错误,如果用户无法访问数据库或类似的东西,如何强制我的引擎重新连接?

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?
Run Code Online (Sandbox Code Playgroud)

zzz*_*eek 11

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

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

  • TL; DR:在sqlalchemy 1.2中你可以做`engine = create_engine("mysql:// user:pw @ host/db",pool_pre_ping = True)`.它检查连接是否仍然存在,如果没有,则重新连接.它有一个小开销(它发送一个`SELECT 1`). (4认同)
  • 也可以使用配置选项进行设置: SQLALCHEMY_ENGINE_OPTIONS = { "pool_pre_ping": True, "pool_recycle": 300, } (2认同)

chj*_*und 5

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

通过采用悲观的错误处理方法,您可以最大程度地消除错误 - 易于实现且非常有效。

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

engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
Run Code Online (Sandbox Code Playgroud)

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


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

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


这两种方法在您的连接会超时的情况下都非常有效,例如过夜/周末。它还使 IT 操作人员更容易关闭数据库,而不必过分担心依赖重启的下游应用程序。然而,这不是灵丹妙药,如果您处理非常关键的交易,那么值得考虑安全交易处理(如 zzzeek 所述)。

  • 我在使用相同会话对象的长期运行过程中遇到了同样的问题。`pool_pre_ping` 有效,但我必须在查询后添加 `session.close()`,因为 pool_pre_ping 仅适用于获取新连接时发生的 `checkout` 事件。 (4认同)