如何使用SQLAlchemy关闭并重新连接以避免事务中的空闲超时

时间:2018-07-11 15:29:39

标签: python postgresql sqlalchemy

我编写了一个Python应用程序,该应用程序使用SQLAlchemy连接到Postgres DB。 enginesessiondb.py

中定义
engine = create_engine(URL(**settings.DATABASE))
session = scoped_session(sessionmaker(bind=engine))

大多数数据库操作在service.py中,它们从session导入db.py

from app.db import engine, session

def get_door_ids():
    result = session.query(ControllerDetail.door_id).distinct().all()
    ids = [c[0] for c in result]
    return ids

def get_last_health_cd(door_id):
    result = session.query(ControllerDetail.door_health_cd).filter(ControllerDetail.door_id == door_id).order_by(ControllerDetail.etl_insert_ts.desc()).first()
    return result[0]

现在一切正常,但是问题是我需要每隔几分钟重复运行同一件事。所以我的主模块中有以下代码:

try:
    while True:
        run_task()
        time.sleep(120)
except KeyboardInterrupt:
    print('Manual break by user')

数据库每分钟空闲连接超时。因此,每当该过程进入睡眠状态超过1分钟时,我都会出错。

psycopg2.InternalError: terminating connection due to idle-in-transaction timeout
SSL connection has been closed unexpectedly

我想知道是否有一种方法可以关闭会话并在time.sleep(120)之后重新打开它,这样它就不会超时。也许在主模块中,我从session导入db作为全局变量,并以某种方式将其传递给services中的方法。我怎么做?我无法从session而不是services导入main中的db,因为mainservices导入了函数。

2 个答案:

答案 0 :(得分:1)

首先,您应该通过提交/回滚来及时结束事务。 Closing会话也将隐式回滚。如果是作用域会话,removing将关闭该会话(并从注册表中删除该会话)。总而言之,"When do I construct a Session, when do I commit it, and when do I close it?"是很好的阅读内容。

一些人可能会感到惊讶的是,Session在您开始与数据库通信后就开始了新的事务。然后,您的工作就是结束该交易。没有看到run_task()的实际作用,很难说哪个部分应该处理会话的生命周期,但是可以肯定地说,如果任务每隔几分钟运行一次,则您不应将事务挂那么长时间。

答案 1 :(得分:0)

  • 增加超时时间

    create_engine(URL(**settings.DATABASE), connect_args={'connect_timeout': 10})

  • 遇到错误时创建一个新会话
  • 您可以通过session.close()
  • 关闭连接