【问题标题】:Flask-SQLAlchemy: How can I call db.create_all() and db.drop_all() without triggering database commits?Flask-SQLAlchemy:如何在不触发数据库提交的情况下调用 db.create_all() 和 db.drop_all()?
【发布时间】:2015-12-22 06:57:15
【问题描述】:

我有一个相当标准的 Flask-SQLAlchemy 设置连接到 PostgreSQL 9.4 数据库。

出于测试目的,我想在数据库事务范围内调用db.create_all(),运行我的测试,然后调用db.drop_all()--all 而不提交该数据库事务。这是可能的,因为 PostgreSQL 在事务中包装了 DDL。

但是,每当我调用db.create_all()db.drop_all() 时,Flask-SQLAlchemy 在创建每个 单独的表后都会发出COMMIT。同样,它会在删除每个表后发出COMMIT

我有 COMMIT_ON_TEARDOWN = True,但 AFAIK 这应该只对最终提交很重要——它不应该导致在每个表之后发生中间提交。

如何更改此行为,以便在不自动触发数据库提交的情况下创建或删除表?

【问题讨论】:

    标签: sqlalchemy flask-sqlalchemy


    【解决方案1】:

    看起来 sqlalchemy 使用 autocommit = True 实现 create_all() 所以可能没有办法改变这种行为。

    相关代码: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/engine/base.py#L199

    https://github.com/zzzeek/sqlalchemy/blob/859379e2fcc4506d036700ba1eca4c0ae526a8ee/lib/sqlalchemy/sql/ddl.py#L60

    更新:

    对于不支持嵌套事务的 MySQL,我的回答是正确的 ==> https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html。 正如@Jeff Widman 在他的回答中提到的那样,有一种方法可以为 PostgreSQL “通过将全局会话替换为在嵌套事务中运行的会话”

    【讨论】:

    • 谢谢,这似乎是正确的答案。但是,我遇到了一篇似乎正在以某种方式解决此问题的博客文章,因为 DDL 提交保留在事务中 - 请参阅“事务 DDL”部分:koo.fi/blog/2015/10/22/… 我阅读并重新阅读了该部分,但不能似乎掌握了它。您能否扩展您的答案以解释他正在做什么来实现这一目标?
    【解决方案2】:

    我是一个 sqlalchemy 菜鸟,但这似乎可以解决问题:

    with contextlib.closing(engine.connect()) as con:
        trans = con.begin()
        database.metadata.create_all(bind=con)
        trans.commit()
    

    【讨论】:

    • 这回答了相反的(和不正确的)问题:如果create_all 没有触发提交,我们将如何人为地这样做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2018-06-15
    • 2022-10-17
    相关资源
    最近更新 更多