强制 Django 提交

发布于 2024-11-28 23:15:48 字数 973 浏览 2 评论 0原文

设置:

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

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

问题:
B 会获取条目(最新条目除外),即使 A分钟之前保存它。

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

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

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

更新:
我发现提交确实发生了 - 我被误导相信它们没有发生,因为 MySQL的通用查询日志只有1秒分辨率
鉴于此和其他新信息,我在这里重新提出了问题

Setup:

  • Python script A inserts data to a database every 15 minutes
  • Python script B queries a few of the latest entries from the database every few minutes

Both use Django's ORM, run on the same machine and use a local MySQL database.

The Problem:
B fetches entries, except for the latest one, even though A saves it minutes before.

I suspected that A doesn't close the transaction, thus B sees the database without the last entry. Indeed when examining the MySQL logs, I noticed the commit for each INSERT happens right before the next INSERT.

Even though it's supposed to be redundant, I added @commit_on_success decorator to the A function that includes the save(), but it did not help.

How can I force Django (or MySQL?!) to commit right after the save()?

UPDATE:
I discovered that the commits DO happen - I was mislead to believe they don't because MySQL's General Query Log only has 1 sec resolution.
In light of this and other new information, I've reasked the question here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

檐上三寸雪 2024-12-05 23:15:48

您可以使用 commit_manually 装饰器并在需要时调用它。

直接来自文档

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

You can use the commit_manually decorator and call it whenever you want.

Straight from the 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()

This answers the question you asked, though I wonder if there might be something else at work.

NOTE: commit_manually was deprecated in 1.6 and removed in 1.8.

我是男神闪亮亮 2024-12-05 23:15:48

该问题是由于MySQL默认具有REPEATABLE-READ事务隔离级别引起的。这意味着相同的查询预计会返回相同的值。改变不会回来。您可以在此处执行两件事:

  1. 在设置中将事务隔离级别设置为 READ-COMMITTED。正如此处所述。
  2. 强制提交,从而关闭脚本 B 上的事务,因此当新事务开始时,您将看到该新事务之前的所有更改。 Model.objects.update() 就可以了。

The problem is caused by that MySQL by default has a REPEATABLE-READ transaction isolation level. That means that the same query is expected to return the same values. Changes won't return. You can do two things here:

  1. Set transaction isolation level to READ-COMMITTED in the settings. As explained here.
  2. Force a commit, thus close the transaction on script B, so as a new transaction starts, you will see all changes before this new transaction. Model.objects.update() does the trick.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文