diff options
| author | Simon Charette <charette.s@gmail.com> | 2022-02-09 01:34:45 -0500 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-09 11:14:50 +0100 |
| commit | d35ce682e31ea4a86c2079c60721fae171f03d7c (patch) | |
| tree | ef28db03ec81c0d5835e0ff34d49099fbd7b80c9 /django | |
| parent | d70b4bea18c96e518ce14dca96085e9265e8ebb6 (diff) | |
Fixed #33506 -- Made QuerySet.bulk_update() perform atomic writes against write database.
The lack of _for_write = True assignment in bulk_update prior to
accessing self.db resulted in the db_for_read database being used to
wrap batched UPDATEs in a transaction.
Also tweaked the batch queryset creation to also ensure they are
executed against the same database as the opened transaction under all
circumstances.
Refs #23646, #33501.
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/query.py | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py index aa10176dc0..0cebcc70d6 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -725,6 +725,7 @@ class QuerySet: ) # PK is used twice in the resulting update query, once in the filter # and once in the WHEN. Each field will also have one CAST. + self._for_write = True connection = connections[self.db] max_batch_size = connection.ops.bulk_batch_size(["pk", "pk"] + fields, objs) batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size @@ -746,9 +747,10 @@ class QuerySet: update_kwargs[field.attname] = case_statement updates.append(([obj.pk for obj in batch_objs], update_kwargs)) rows_updated = 0 + queryset = self.using(self.db) with transaction.atomic(using=self.db, savepoint=False): for pks, update_kwargs in updates: - rows_updated += self.filter(pk__in=pks).update(**update_kwargs) + rows_updated += queryset.filter(pk__in=pks).update(**update_kwargs) return rows_updated bulk_update.alters_data = True |
