2015-04-04 43 views
0

我很关心一件事情。
使用Django 1.7(最默认安装中的MySQL)我正在向Django REST框架APIView发布POST。 在那里我做了:Django并发get_or_create

try: 
    MyModel.objects.get(**some_kwargs) 
except MyModel.DoesNotExist: 
    MyModel.objects.custom_create(**some_kwargs) # This also creates relative models 

现在,如果我会做大量的并发请求会发生什么?
正如我猜你期望我只想要第一个并发请求来创建一个对象,任何其他应该得到创建一个。

我准备好了,谢谢Django吗?必须研究隔离,交易,原子性?还是更关于锁定桌子?如何(单位)测试它?

请指导我。

回答

1

这不足以避免竞争条件,因为另一个请求可能会创建您想要在get()custom_create()之间进行检索的模型。如果在数据库级别实施唯一性,则您的custom_create()方法可能会失败,并显示IntegrityError。如果不是,你的方法很好,但你不能防止由于竞争条件造成的重复条目。

Django提供了get_or_create()函数。如果您的数据库执行唯一性,这可以防止竞争条件。它使用create()方法,但不是您的custom_create()方法,因此如果可以接受,则必须覆盖它。否则,您可以通过source code查询get_or_create()并使用您的自定义创建方法自行实施。

get_or_create的核心假设是唯一性在数据库级别上实施。由于这种强制执行,create如果发生竞态条件将失败,并且get_or_create可能会退回到获取竞争条件期间创建的对象。如果缺少此强制执行,create在竞争条件期间不会失败,并且会创建重复条目(使用不同的PK)。

+0

仍然没有运气:(现在我正在尝试postgresql和相同的效果(也试图在MySQL的READ COMMITTED)和一个简单的'MyModel.objects.get_or_create'由Django提供 - 有时它可以(只有一个创建),有时第二个线程再次创建,然后第三个抛出'MultipleObjectsReturned'。用这个测试:https://www.caktusgroup.com/blog/2009/05/26/testing-django-views-for-concurrency-issues/ – McAbra 2015-04-04 21:46:17

+0

@McAbra你是否在数据库级别的'** some_kwargs'上强制执行唯一性?否则,没有一种可以防止重复的方法。 – knbk 2015-04-04 21:50:44

+0

我刚刚在这个模型的三个attrs上做了一个'unique_together',它没有帮助,那是什么你的意思是吗? – McAbra 2015-04-04 22:07:28