【问题标题】:sqlalchemy, postgresql and relationship stuck in "idle in transaction"sqlalchemy、postgresql 和关系陷入“事务中的空闲”
【发布时间】:2013-08-28 14:22:18
【问题描述】:

我有一个与 sqlalchemy 和 postgresql 相关的问题。

class Profile(Base):
  ...

  roles = relationship('Role', secondary=role_profiles,
                       backref='profiles', lazy='dynamic')

运行时(current_userProfile 类的一个实例):

roles = current_user.roles.filter().all()

使用 sqlalchemy 我得到 idle in transaction 用于读取 postgresql 中的配置文件的所有选择。

编辑:

通过回显查询,我看到每个选择都以:

BEGIN (implicit)

另一个修改:

添加后

pool_size=20, max_overflow=0

对于create_engine,当空闲数量变大时,idle in transaction-statements 似乎正在回滚。对此有任何想法吗?这会是解决问题的坏方法吗?

我该如何管理以及如何摆脱 BEGIN 的选择?

【问题讨论】:

  • 你试过pool_timeout=90吗?我找到了here in the doc
  • 我认为这并不能真正解决问题。我想摆脱选择时开始或选择时自动提交。
  • 您没有正确结束交易。您必须commitrollback 您的交易。 begin 部分是隐含的(如您所述),但需要正确结束。另外:为什么你有一个空的过滤器语句?那有意义吗?您是在网络环境中还是在不同的环境中?最后,虽然非常不推荐,但您可以使用autocommit 模式(但实际上,不要)。
  • @javex,谢谢。我一直在阅读并从交易中获得了大部分,但我的relationsships 中仍有一些我无法真正触及。 sqlalchemy 会自动关闭这些吗?。
  • 通常您应该在单个会话上操作。尽管如此,我还是不明白你在做current_user.roles.filter().all() 时想要达到的目标。为什么不直接做current_user.roles?这给出了一个列表并在 current_user 所属的会话的上下文中自动执行(例如,如果您这样查询:session.query(User).filter(User.id == some_id).one() 那么这一切都将被自动处理。

标签: python session transactions sqlalchemy


【解决方案1】:

默认情况下,SQLA 总是在事务中运行(一些信息here)。在 Web 上下文中,大多数框架会在请求结束时为您处理提交此事务(例如 pyramid_tm)。如果您没有使用框架,或者这是另一种类型的应用程序,您将希望在完成时或在适当的时候提交或回滚。

也许可以配置 SQLA,使其不会自动启动事务,但据我所知,这不是它的预期用途,所以你可能会比较幸运,不要试图与之抗争: )。

【讨论】:

    【解决方案2】:

    从 SQLAlchemy 0.8.2 开始,您可以在调用 create_engine() 时禁用隐式 BEGIN 语句

    engine = create_engine(uri, isolation_level="AUTOCOMMIT")
    

    这种变化有一些微妙的含义。首先,那些没有悄悄隐藏在未终止事务中的语句将被悄悄忽略

    session.execute("DELETE FROM department WHERE department_id=18")
    sys.exit(0)
    

    默认

    LOG:  statement: BEGIN
    LOG:  statement: show standard_conforming_strings
    LOG:  statement: DELETE FROM department WHERE department_id=18
    LOG:  unexpected EOF on client connection with an open transaction
    

    自动提交

    LOG:  statement: show standard_conforming_strings
    LOG:  statement: DELETE FROM department WHERE department_id=18
    

    第二,更新多个更新不再是自动的,rollback() 只是有条件有效:

    department = Department(u"HR")
    session.add(department)
    session.flush()
    employee = Employee(department.department_id, u'Bob')
    session.add(employee)
    session.rollback()
    

    默认

    LOG:  statement: BEGIN
    LOG:  statement: INSERT INTO department (name) VALUES ('HR') RETURNING department.department_id
    LOG:  statement: ROLLBACK
    

    自动提交

    LOG:  statement: INSERT INTO department (name) VALUES ('HR') RETURNING department.department_id
    

    在 Engine 对象上设置 SQLAlchemy 的 isolation_level 对 许多应用程序。不幸的是,Session.begin() 并不总是意味着BEGIN TRANSACTION;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 2015-05-16
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-21
      相关资源
      最近更新 更多