#36213: Add warning to documentation: QuerySet.update can execute two separate 
SQL
queries when using MySQL
-------------------------------------+-------------------------------------
     Reporter:  Babak                |                     Type:
                                     |  Uncategorized
       Status:  new                  |                Component:
                                     |  Documentation
      Version:                       |                 Severity:  Normal
     Keywords:  mysql self-select    |             Triage Stage:
  race-condition                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 When you have a QuerySet that has filter conditions based on related
 tables, the `QuerySet.update()` function will execute two separate SQL
 queries (a `SELECT`, followed by an `UPDATE`).

 Examples:

 `BlogPost.objects.filter(published=True).update(foo="bar")` (Causes a
 single `UPDATE`)

 `BlogPost.objects.filter(published=True, author__name="Foo
 Bar").update(foo="bar")` (Causes `SELECT` THEN `UPDATE`)

 As I was told in the [https://forum.djangoproject.com/t/queryset-update-
 silently-turns-into-select-update-mysql/39095/2 forum] (thanks charettes),
 this is an undocumented
 
[https://github.com/django/django/blob/240421c7c4c81fe5df26274b807266bd4ca73d7f/django/db/backends/mysql/features.py#L165-L167
 MySQL-only behaviour] because MySQL [https://dbfiddle.uk/Zfz_e9Kw doesn't
 allow self-select updates].

 This will **silently cause nasty race conditions** since the update is no
 longer running as a single SQL statement.

 Currently the docs for `QuerySet.update` say:

    Using update() also prevents a race condition wherein something might
 change in your database in the short period of time between loading the
 object and calling save().

 But in the case that I described, it causes the exact same type of race
 condition that the docs suggest that it prevents.

 If the users are aware of this behaviour they can take care to avoid such
 filter conditions or to use alternative transaction handling mechanisms to
 ensure atomic behaviour.

 I'd like to suggest for a warning to be added to the documentation about
 this.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36213>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/010701953ab074d4-3e25e57e-207e-4e4a-a693-4612f67233c2-000000%40eu-central-1.amazonses.com.

Reply via email to