On Wed, Aug 8, 2012 at 9:25 AM, Cal Leeming [Simplicity Media Ltd] <
[email protected]> wrote:

> I'm not entirely sure that suggesting every query needs to be committed is
> the right way forward either, given that you only need to commit once
> before get_or_create() is called to prevent the issue.
>
> Could you expand on why you feel every query would need to be committed?
>

get_or_create does:

1 - get
2 - if get fails due to DoesNotExist, create
3 - if create fails due to IntegrityError, get again

The problem with repeatable read transaction level is that step 3 can never
return something other than what was found (or not) in step 1. If some
other thread, between the times at which 1 and 2 happen, creates what this
thread is attempting to get_or_create, then the get_or_create is going to
fail, because the get will still find nothing in step 3, causing
get_or_create to re-raise the IntegrityError from step 2.

Issuing a commit before calling get_or_create doesn't fix this race
condition that exists within the get_or_create code itself. Such a pre-call
commit is only going to be helpful if the current transaction has already
done a read that has fixed what is going to be returned by the DB in step
1. If that has happened, then committing before calling get_or_create will
reduce the likelihood of hitting the race condition, since step 1 may then
read a row that has been created subsequent to the last read by this thread
but before this thread gets to step 1 in get_or_create. Essentially the
pre-commit narrows the race condition window in this case. (If no read has
yet been done by the transaction to already set in stone what this
transaction will read in step 1, then committing before calling
get_or_create does not help at all.)

Regardless of what's done before the call into get_or_create, there's still
a small window of opportunity, between steps 1 and 2, for get_or_create to
fail. get_or_create requires either DB level autocommit or read committed
transaction isolation level in order for it to be free of this race
condition. Recommending anything else in Django's docs would be misleading.

Karen

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to