Thanks for the detailed explanation on this.

Am I correct in assuming you are referring to the following decorator as
being the fix for the problem?

@transaction.autocommit
def viewfunc(request):
    pass


On Thu, Aug 9, 2012 at 3:55 AM, Karen Tracey <[email protected]> wrote:

> 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.
>



-- 

*Cal Leeming
Technical Support | Simplicity Media Ltd
**US *310-362-7070 | *UK *02476 100401 | *Direct *02476 100402

*Available 24 hours a day, 7 days a week.*

-- 
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