【问题标题】:SQLAlchemy/Pyramid DBSession refresh issueSQLAlchemy/Pyramid DBSession 刷新问题
【发布时间】:2014-10-23 20:12:42
【问题描述】:

这是我的场景: 第一个视图呈现表单,数据进入第二个视图,我将其存储在数据库(MySQL)中并重定向到第三个视图,该视图显示了写入数据库的内容:

Stoing to db:
    DBSession.add(object)
    transaction.commit()

DB Session:
    DBSession = scoped_session(sessionmaker(expire_on_commit=False,
                                            autocommit=False, 
                                            extension=ZopeTransactionExtension()))

之后,当我多次刷新页面时,有时我会看到数据库更改,有时不会,一次是旧数据,第二次是新数据,依此类推... 当我重新启动服务器(本地,pserve)时,数据库数据是最新的。

也许是创建会话的问题?

【问题讨论】:

  • 您能否编辑您的问题以显示 DBSession 变量的确切定义位置以及如何从第二个视图重定向到第三个视图?您还可以提供视图功能的粗略轮廓

标签: python mysql sqlalchemy pyramid


【解决方案1】:

检查 MySQL 的transaction isolation level

InnoDB 的默认值为REPEATABLE READ:“同一个事务中的所有一致性读取都读取第一次读取建立的快照。”

您可以在调用create_engine 时指定隔离级别。请参阅SQLAlchemy docs

我建议您尝试READ COMMITTED 隔离级别,看看是否能解决您的问题。

【讨论】:

  • 抱歉,它没有帮助 - 保存到 db 并重定向后出现同样的问题 - 一次刷新时我有新数据,第二次旧数据,几次刷新后它“稳定”
  • 嗯。我能想到的唯一另一件事是ZopeTransactionExtension。我不确定它的作用,你可以不试试吗?
  • ZopeTransactionExtension 确保打开的每个会话都加入一个活动事务,没有它也是一样的。
  • 可能是 HTTPFound 重定向的问题?
  • 我试过 postgres - 同样,奇怪的是这个问题不是全球性的,也许我看错了部分代码......
【解决方案2】:

尚不清楚您的事务对象是什么或它如何连接到 SQLAlchemy 数据库会话。我在 Pyramid 文档中看不到有关事务的任何内容,并且在您的代码中看不到将事务对象链接到 SQLAlchemy 会话的任何内容,因此可能缺少一些配置。你这个代码基于什么例子?

另外:sessionmaker 调用通常在文件分数处完成以创建单个会话工厂,然后重复使用该工厂从同一源创建会话对象。 "the sessionmaker() function is normally used to create a top level Session configuration which can then be used throughout an application without the need to repeat the configurational arguments."

可能的情况是,由于您正在创建多个会话工厂,因此有些数据应该在会话之间共享,但实际上并未共享,因为每个工厂都创建了一次。试试just calling sessionmaker once 看看会不会有什么不同。

【讨论】:

    【解决方案3】:

    我相信您的问题很可能是一个持续的会话。默认情况下,Pyramids 会在提交后使会话中的所有对象过期——这意味着 SQLA 将在您下次需要它们时从数据库中获取它们,并且它们将是新鲜的。

    您已通过指示“expire_on_commit=False”覆盖了此默认值——因此,如果您打算让该会话对象在后续请求中获取新数据,请确保在提交更改后调用 session.expire_all()。 (会话对象对于 Pyramid 中的多个请求是相同的,但不能保证您获得相同的线程范围会话)我建议不要将提交时的过期设置为 false,或使用非全局会话:请参阅http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/database/sqlalchemy.html#using-a-non-global-session

    或者,您可以确保在必要时使对象过期,因为知道未过期的对象将按原样保留在内存中并且不会被刷新,并且可能与不同线程范围会话中的同一对象不同。

    【讨论】:

      【解决方案4】:

      问题是您正在设置expire_on_commit=False。如果你删除它,它应该可以工作。你可以在http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#sqlalchemy.orm.session.Session.commit上阅读更多关于它的作用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-25
        • 2013-11-23
        • 2013-04-18
        • 1970-01-01
        • 2011-11-14
        • 1970-01-01
        • 2014-03-04
        • 1970-01-01
        相关资源
        最近更新 更多