[Django] #24009: get_or_create can raise an IntegrityError in race conditions

20 views
Skip to first unread message

Django

unread,
Dec 17, 2014, 9:24:10 AM12/17/14
to django-...@googlegroups.com
#24009: get_or_create can raise an IntegrityError in race conditions
-------------------------------+--------------------
Reporter: lanzz | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 1.7
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------
`get_or_create` is described as being atomic in the documentation, but
that is not the case. Since it first tries to retrieve an existing record
and if that fails it tries to create a new one, another thread can create
that record in the small interval between the two operations. This will
not result in data corruption as the database will enforce its
constraints, but it makes the whole convenience method not that
convenient, if I also need to handle this in a `try` block around its
invocation. If I _need_ to do `try: get_or_create() except IntegrityError:
get()` anyway, it makes no sense to use `get_or_create` in the first
place, that logic would work if I just try to create the entity and only
retrieve it if the create raises an `IntegrityError`.

When I call `get_or_create` I expect it to return the existing record, or
to create a new record if one does not exist yet. Getting an
`IntegrityError` there is like saying "there's no existing record, but I
cannot create a new one because one already exists".

--
Ticket URL: <https://code.djangoproject.com/ticket/24009>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Dec 17, 2014, 9:27:38 AM12/17/14
to django-...@googlegroups.com
#24009: get_or_create can raise an IntegrityError in race conditions
-------------------------------+--------------------------------------

Reporter: lanzz | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 1.7
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by timgraham):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

This may be a duplicate of #13906. Are you using MySQL with `REPEATABLE
READ`?

--
Ticket URL: <https://code.djangoproject.com/ticket/24009#comment:1>

Django

unread,
Dec 17, 2014, 10:12:06 AM12/17/14
to django-...@googlegroups.com
#24009: get_or_create can raise an IntegrityError in race conditions
-------------------------------+--------------------------------------

Reporter: lanzz | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 1.7
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by lanzz):

No, I'm using PostgreSQL, and wrapping each `get_or_create` in an
individual transaction context will again make `get_or_create` worthless
by requiring at least as much boilerplate around it as it would take to
implement the get-or-create logic myself without using `get_or_create`.

--
Ticket URL: <https://code.djangoproject.com/ticket/24009#comment:2>

Django

unread,
Dec 19, 2014, 9:37:08 AM12/19/14
to django-...@googlegroups.com
#24009: get_or_create can raise an IntegrityError in race conditions
-------------------------------+--------------------------------------

Reporter: lanzz | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 1.7
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by timgraham):

As far as I can tell, the `IntegrityError` you describe
[https://github.com/django/django/blob/6403e07c5093e0244497293f31f5f73cebe85b66/django/db/models/query.py#L468-L483
should be caught by Django]. Did you run into this problem with Django
1.7?

--
Ticket URL: <https://code.djangoproject.com/ticket/24009#comment:3>

Django

unread,
Dec 22, 2014, 11:53:37 AM12/22/14
to django-...@googlegroups.com
#24009: get_or_create can raise an IntegrityError in race conditions
-------------------------------+--------------------------------------
Reporter: lanzz | Owner: nobody
Type: Uncategorized | Status: closed
Component: Uncategorized | Version: 1.7
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage: Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by timgraham):

* status: new => closed
* resolution: => needsinfo


--
Ticket URL: <https://code.djangoproject.com/ticket/24009#comment:4>

Reply all
Reply to author
Forward
0 new messages