Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Revert "Fixed #16865 -- Made get_or_create use read database for init…

…ial get query."

Thanks to Jeremy Dunck for pointing out the problem with this change. If in a
single transaction, the master deletes a record and then get_or_creates a
similar record, under the new behavior the get_or_create would find the record
in the slave db and fail to re-create it, leaving the record nonexistent, which
violates the contract of get_or_create that the record should always exist
afterwards. We need to do everything against the master here in order to ensure
correctness.

This reverts commit 901af86.
  • Loading branch information...
commit 4e9a74b81df1c7aaea2f90a3a4911920e134b275 1 parent 901af86
Carl Meyer authored
2  django/db/models/query.py
@@ -455,9 +455,9 @@ def get_or_create(self, **kwargs):
455 455
             if f.attname in lookup:
456 456
                 lookup[f.name] = lookup.pop(f.attname)
457 457
         try:
  458
+            self._for_write = True
458 459
             return self.get(**lookup), False
459 460
         except self.model.DoesNotExist:
460  
-            self._for_write = True
461 461
             try:
462 462
                 params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
463 463
                 params.update(defaults)
9  docs/releases/1.5.txt
@@ -338,15 +338,6 @@ Miscellaneous
338 338
   needs. The new default value is `0666` (octal) and the current umask value
339 339
   is first masked out.
340 340
 
341  
-* In a multi-database situation, ``get_or_create()`` will now use a read
342  
-  database for the initial ``get`` attempt (previously, it used only the write
343  
-  database for all queries). This change reduces load on the write (master)
344  
-  database, in exchange for slightly more frequent false-negatives on the
345  
-  initial ``get`` due to replication lag. In those cases the subsequent insert
346  
-  will still go to the master and fail, after which the existing object will be
347  
-  fetched from the master.
348  
-
349  
-
350 341
 Features deprecated in 1.5
351 342
 ==========================
352 343
 
24  tests/modeltests/get_or_create/tests.py
@@ -64,27 +64,3 @@ def test_get_or_create(self):
64 64
             formatted_traceback = traceback.format_exc()
65 65
             self.assertIn('obj.save', formatted_traceback)
66 66
 
67  
-
68  
-    def test_initial_get_on_read_db(self):
69  
-        """
70  
-        get_or_create should only set _for_write when it's actually doing a
71  
-        create action. This makes sure that the initial .get() will be able to
72  
-        use a slave database. Specially when some form of database pinning is
73  
-        in place this will help to not put all the SELECT queries on the
74  
-        master. Refs #16865.
75  
-
76  
-        """
77  
-        qs = Person.objects.get_query_set()
78  
-        p, created = qs.get_or_create(
79  
-            first_name="Stuart", last_name="Sutcliffe", defaults={
80  
-                "birthday": date(1940, 6, 23),
81  
-                }
82  
-            )
83  
-        self.assertTrue(created)
84  
-        self.assertTrue(qs._for_write)
85  
-
86  
-        qs = Person.objects.get_query_set()
87  
-        p, created = qs.get_or_create(
88  
-            first_name="Stuart", last_name="Sutcliffe")
89  
-        self.assertFalse(created)
90  
-        self.assertFalse(qs._for_write)

0 notes on commit 4e9a74b

Please sign in to comment.
Something went wrong with that request. Please try again.