使用 Django ORM 捕获竞争条件的正确方法 + MySQL/InnoDB

发布于 2024-09-11 04:47:47 字数 820 浏览 5 评论 0原文

我的应用程序的一部分存在竞争条件,其中多个线程最终可能创建相同的持久对象。所以我实现了如下所示的代码:

from foobar.models import Bar

def testomatic(request):
    bar = None
    tries = 0
    while not bar:
        try:
            bar = Bar.objects.get(b=2)

        except Bar.DoesNotExist:
            time.sleep(10) # put in here to force the race condition
            bar = Bar(a = 2, b = 2)
            try:
                bar.save()
            except IntegrityError:
                tries += 1
                bar = None

            if tries > 1:
               raise Exception("something bad happened")

    return HttpResponse("tries = %s" % tries)

这在我的测试环境中工作正常 - 但是当我使用“真实”类运行它时,它似乎旋转,反复从 get() 中得不到任何东西,但总是得到一个 IntegrityError在保存()上。

我使用 MySQL/InnoDB 作为数据库引擎。 MVCC 处理是否存在某些问题,导致我无法获取记录,但在尝试创建记录时却出现重复键错误?

One part of my application has a race condition where multiple threads could end up creating the same persistent object. So I have implemented code that looks like this:

from foobar.models import Bar

def testomatic(request):
    bar = None
    tries = 0
    while not bar:
        try:
            bar = Bar.objects.get(b=2)

        except Bar.DoesNotExist:
            time.sleep(10) # put in here to force the race condition
            bar = Bar(a = 2, b = 2)
            try:
                bar.save()
            except IntegrityError:
                tries += 1
                bar = None

            if tries > 1:
               raise Exception("something bad happened")

    return HttpResponse("tries = %s" % tries)

And this works OK in my test environment -- but when I run this with "real" classes, it seems to spin, repeatedly getting nothing from the get(), but always getting an IntegrityError on the save().

I'm using MySQL/InnoDB as a database engine. Is there something about the MVCC handling that is preventing me from getting a record, but giving me a duplicate key error when I try to create it?

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

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

发布评论

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

评论(1

挽梦忆笙歌 2024-09-18 04:47:47

正确的方法是使用原始 SQL,以便在执行初始 SELECT 时锁定表,然后创建并保存对象(如果对象不存在),然后解锁表。

The correct way to do this is to drop to raw SQL so that you can lock the table when doing the initial SELECT, and then creating and saving the object if it does not exist, then unlocking the table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文