【问题标题】:Django1.6 IntegrityError despite transaction.atomic()?Django1.6 IntegrityError 尽管 transaction.atomic()?
【发布时间】:2014-07-02 05:56:02
【问题描述】:

transaction.atomic() 内,我正在删除并重新创建对象。 Django 位于 3-worker gunicorn 后面,数据库是 postgres。

问题:当同时向服务器发送大量请求时,Django 会抛出 一些 IntegrityErrors

IntegrityError: duplicate key value violates unique constraint "atomic_atomictest_name_key"
DETAIL:  Key (name)=(foo) already exists.

例子:

models.py

class AtomicTest(models.Model):
    name = models.TextField(null=False, unique=True)

views.py

def test_atomic(request):
    with transaction.atomic():
        models.AtomicTest.objects.filter(name='foo').delete()
        models.AtomicTest(name='foo').save()
    return http.HttpResponse('OK')

在我的理解中,IntegrityErrors 不应该发生。谁能解释一下为什么?

【问题讨论】:

    标签: python concurrency atomic gunicorn django-1.6


    【解决方案1】:

    IntegrityError 仍然可以与transaction.atomic() 一起发生。交易可以同时发生;它们只有在提交之前彼此隔离,此时由 Postgres 尝试协调更改。如果 Postgres 决定一个或多个事务试图创建违反唯一性约束的行,它将回滚这些事务。

    transaction.atomic() 所做的是确保块中的所有命令在其中任何一个失败时都回滚。这样你就不会遇到delete() 成功并提交但save() 失败的情况。

    在这种情况下,transaction.atomic() 实际上可能会导致您的问题,因为它会延迟 delete() 立即生效。

    【讨论】:

    • 感谢您的精彩解释。我想除了使用锁来防止数据库抛出 IntegrityError 之外别无他法?
    • 如果IntegrityError 是由行编辑引起的,您可以锁定该行。但是,在这种情况下,它是由行创建引起的。除了手动管理锁定机制之外,没有其他方法可以锁定行。但是,在这种情况下,IntegrityError 似乎不是问题?毕竟,问题是该行已经存在,没有必要创建两次。也许您可以抓住错误并继续前进。
    • 我现在正在这样做 :-) 再次感谢!
    猜你喜欢
    • 2014-03-16
    • 2020-08-28
    • 2019-09-02
    • 2015-01-12
    • 2021-08-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    相关资源
    最近更新 更多