Hi Amymeric,
 
That makes sense about the different (and default) MySQL transactional mode.
 
I don't know about the Django 1.6 transaction changes yet, but I am curious 
of it will break my managed transaction blocks in existing Django 1.3.x 
code. 
 
For example, to handle this get_or_create issue I outlined, I do something 
like the following:
 
        var = None  # initialize the variable
        try:
            var, c = self.model.objects.get_or_create(url=url)
        except Exception, e:
            log.error("Exception in get_or_create: {0}".format(e))
            transaction.commit()
            vars = self.model.objects.filter(url=url)
            var = vars[0]
        ...
        transaction.commit()
        return var
 
 
Will this still work in Django 1.6 for our use case assuming our MySQL 
configuration stays the same default as it has been? ...
 
 
Thanks for your replies,



On Thursday, April 4, 2013 11:23:43 PM UTC-4, Matteius wrote:
>
>
> Greetings Developers,
>
> Today at work I fixed a thread safety issue in our code whereby two 
> threads were calling get_or_create on the same URL which has a uniqueness 
> constraint.  It was in some cases raising an IntegrityError in sentry even 
> after I converted our atomically incorrect code to use get_or_create 
> proving to me it must be two different threads performing the same action.  
> Let me elaborate ...
>
> Django's get_or_create does a Get, failing that a create, failing that a 
> rollback and another get.   For some reason in MySQL, and to me 
> conceptually the code roll back to prior to the commit when the other 
> thread wins in the create block and saves the object, it still doesn't 
> exist when the other thread tries to get it a final time, because I believe 
> it rolled back to the earlier pre-save savepoint.
>
> Here is the final part of the get_or_create:
>
>                 obj = self.model(**params)
>                 sid = transaction.*savepoint*(using=self.db)
>                 obj.save(force_insert=True, using=self.db)
>                 transaction.savepoint_commit(sid, using=self.db)
>                 return obj, True
>             except *IntegrityError* as e:
>                 transaction.savepoint_rollback(sid, using=self.db)
>                 exc_info = sys.exc_info()
>                 try:
>                     return self.get(**lookup), False
>                 except self.model.DoesNotExist:
>                  *   # Re-raise the IntegrityError* with its original 
> traceback.
>                     six.reraise(*exc_info)
>
>
> The question for me is:  *Why wouldn't we want this to be this way?*:
>
>                 obj = self.model(**params)
>                 sid = transaction.*savepoint*(using=self.db)
>                 obj.save(force_insert=True, using=self.db)
>                 transaction.savepoint_commit(sid, using=self.db)
>                 return obj, True
>             except *IntegrityError* as e:
>                 transaction.savepoint_rollback(sid, using=self.db)
>                 exc_info = sys.exc_info()
>                 try:
>                     *transaction.commit()*  # To refresh the DB view for 
> thread safety
>                     return self.get(**lookup), False   # ... Get succeeds 
> now in a thread unsafe world
>                 except self.model.DoesNotExist:
>                  *   # Re-raise the IntegrityError* with its original 
> traceback.
>                     six.reraise(*exc_info)
>
>
> *Also ---*  On the Django Website, The Django Downloads page Django 
> gtihub tarball master is a 1.4 zip file.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to