使用SQLAlchemy的PSQL连接关闭时间延迟

时间:2018-01-04 16:48:53

标签: python postgresql session sqlalchemy psql

  • 为什么在调用session.close()和会话实际关闭之间似乎存在显着延迟?
  • 我以一种感觉不对的方式“用完”连接。有没有更好的方法来做这个或我缺少的设计模式?

按照指南here,我使用以下代码,复制完整性:

@contextmanager
def session_scope():
    """Provide a transactional scope around a series of operations."""
    session = Session()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()


def run_my_program():
    with session_scope() as session:
        ThingOne().go(session)
        ThingTwo().go(session)

这对于可靠地提交数据和避免无效会话非常有用。 问题在于达到连接限制。

例如,假设我有一个页面,每次访问可以进行5次异步调用。如果我访问该页面并快速连续点击刷新,它将生成5 * number_times_refreshed个连接。它最终将关闭它们,但是时间延迟不可忽略。

1 个答案:

答案 0 :(得分:0)

问题是使用sessionmaker()并绑定数据库引擎。具体来说,这不是一个好方法:

def newSession():
    engine = create_engine(settings.DATABASE_URL)
    Base.metadata.bind = engine
    DBSession = sessionmaker(bind=engine)

    session = DBSession()

    return session

@contextmanager
def session_scope():
    session = newSession()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

这会为每个请求创建一个新引擎。除了这是一个糟糕的模式,它引起了混淆"连接"正在关闭。在这种情况下,我们有一个"会话"和" DBSession"。会话确实通过session.close()关闭,但这并没有触及" DBSession"。

更好的方式(解决方案):

engine = create_engine(settings.DATABASE_URL)
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)

@contextmanager
def session_scope():
    session = DBSession()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

为应用的生命周期创建一个连接