Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django concurrent get_or_create

I'm concerned about one thing.
Using Django 1.7 (MySQL in the most default installation) I'm making a POST to a Django REST Framework APIView. Over there I'm doing a:

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

Now what will happen if I'll do plenty of concurrent requests?
As I guess you expect I want only the first concurrent request to create an object and any other should get the created one.

Am I ready to go thanks do Django? Have to study about isolation, transactions, atomicity? Or is it more about locking the table? How to (unit) test it?

Please guide me.

like image 935
McAbra Avatar asked Feb 10 '23 12:02

McAbra


1 Answers

This is not enough to avoid race conditions, as another request can create the model you intended to retrieve between get() and custom_create(). If uniqueness is enforced on a database level, your custom_create() method can fail with an IntegrityError. If it is not, your method is fine, but you cannot prevent duplicate entries due to race conditions.

Django provides the get_or_create() function. This safeguards against race conditions if uniqueness is enforced by your database. It uses the create() method, however, not your custom_create() method, so you'll have to override it if it is acceptable. Otherwise, you can checkout out the source code for get_or_create() and implement it yourself with your custom create method.

The core assumption of get_or_create is that uniqueness is enforced on a database level. Due to this enforcement, create fails if a race condition occurs, and get_or_create can fall back to fetching the object created during the race condition. If this enforcement is missing, the create doesn't fail during a race condition, and a duplicate entry (with a different PK) will be created.

like image 176
knbk Avatar answered Feb 13 '23 02:02

knbk