Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This could be an off-shoot of the same problem as here:</p> <p><a href="https://stackoverflow.com/questions/2221247/why-doesnt-this-loop-display-an-updated-object-count-every-five-seconds/2221400">Why doesn&#39;t this loop display an updated object count every five seconds?</a></p> <p>Basically <a href="http://code.djangoproject.com/browser/django/trunk/django/db/models/query.py#L353" rel="nofollow noreferrer">get_or_create</a> <em>can fail</em> - if you take a look at its source, there you'll see that it's: get, if-problem: save+some_trickery, if-still-problem: get again, if-still-problem: surrender and raise. </p> <p>This means that if there are two simultaneous threads (or processes) running <code>create_or_update_myobj</code>, both trying to get_or_create the same object, then:</p> <ul> <li>first thread tries to get it - but it doesn't yet exist,</li> <li>so, the thread tries to create it, but before the object is created...</li> <li>...second thread tries to get it - and this obviously fails</li> <li>now, because of the default AUTOCOMMIT=OFF for MySQLdb database connection, and REPEATABLE READ serializable level, both threads have frozen their views of MyObj table.</li> <li>subsequently, first thread creates its object and returns it gracefully, but...</li> <li>...second thread cannot create anything as it would violate <code>unique</code> constraint</li> <li>what's funny, subsequent <code>get</code> on the second thread doesn't see the object created in the first thread, due to the frozen view of MyObj table</li> </ul> <p>So, if you want to safely <code>get_or_create</code> anything, try something like this:</p> <pre><code> @transaction.commit_on_success def my_get_or_create(...): try: obj = MyObj.objects.create(...) except IntegrityError: transaction.commit() obj = MyObj.objects.get(...) return obj </code></pre> <h2>Edited on 27/05/2010</h2> <p>There is also a second solution to the problem - using READ COMMITED isolation level, instead of REPEATABLE READ. But it's less tested (at least in MySQL), so there might be more bugs/problems with it - but at least it allows tying views to transactions, without committing in the middle.</p> <h2>Edited on 22/01/2012</h2> <p>Here are some good blog posts (not mine) about MySQL and Django, related to this question:</p> <p><a href="http://www.no-ack.org/2010/07/mysql-transactions-and-django.html" rel="nofollow noreferrer">http://www.no-ack.org/2010/07/mysql-transactions-and-django.html</a></p> <p><a href="http://www.no-ack.org/2011/05/broken-transaction-management-in-mysql.html" rel="nofollow noreferrer">http://www.no-ack.org/2011/05/broken-transaction-management-in-mysql.html</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload