【问题标题】:Force Django to commit强制 Django 提交
【发布时间】:2011-10-24 21:53:49
【问题描述】:

设置:

  • Python 脚本 A 每 15 分钟向数据库插入一次数据
  • Python 脚本 B 每隔几分钟从数据库中查询一些最新条目

两者都使用 Django 的 ORM,在同一台机器上运行并使用本地 MySQL 数据库。

问题:
B 获取条目,除了最新的条目,尽管 A 保存了 分钟 之前。

我怀疑 A 没有关闭事务,因此 B 看到没有最后一个条目的数据库。事实上,在检查 MySQL 日志时,我注意到每个 INSERTcommit 发生在 下一个 INSERT 之前。

即使它应该是多余的,我也将@commit_on_success 装饰器添加到包含save()A 函数中,但它没有帮助。

如何强制 Django(或 MySQL?!)在 save() 之后立即提交?

更新:
我发现提交 DO 发生了——我被误导相信它们不会发生,因为MySQL's General Query Log only has 1 sec resolution
鉴于此信息和其他新信息,我重新提出了here 的问题。

【问题讨论】:

    标签: mysql django transactions commit


    【解决方案1】:

    您可以使用 commit_manually 装饰器并随时调用它。

    直接来自documentation

    from django.db import transaction
    
    @transaction.commit_manually
    def viewfunc(request):
        ...
        # You can commit/rollback however and whenever you want
        transaction.commit()
        ...
    
        # But you've got to remember to do it yourself!
        try:
            ...
        except:
            transaction.rollback()
        else:
            transaction.commit()
    

    这回答了您提出的问题,不过我想知道是否还有其他问题在起作用。

    注意:commit_manually1.6 中已弃用并在 1.8 中删除。

    【讨论】:

    • 这与@commit_on_success 有何不同? (切换到手动提交会损害我们的正常运行时间,所以我想在对系统进行回火之前更好地了解一下)
    • commit_on_success 仅在包装函数返回后运行提交;如果它闲置而不返回,那将无济于事。 commit_manually 允许您在上次保存后立即调用提交。我不确定你的代码在做什么,所以我现在能想到的就这些了。
    • 虽然我发现我的问题出在其他地方,但我相信您的回答对于那些搜索强制 django 提交的人来说意义重大,因此我将其标记为正确答案
    【解决方案2】:

    这个问题是因为 MySQL 默认有一个 REPEATABLE-READ 事务隔离级别。这意味着相同的查询应该返回相同的值。更改不会返回。你可以在这里做两件事:

    1. 在设置中将事务隔离级别设置为 READ-COMMITTED。正如here所解释的那样。
    2. 强制提交,从而关闭脚本 B 上的事务,以便在新事务开始时,您将看到此新事务之前的所有更改。 Model.objects.update() 可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      相关资源
      最近更新 更多