Interesting. Thanks for the rundown. Looking forward to 1.6.

On Tuesday, May 28, 2013 6:40:28 PM UTC-4, akaariai wrote:
>
> On 29 touko, 01:07, Chris Conover <clc...@gmail.com> wrote: 
> > Adding commit_unless_managed() before the get() seems to fix the 
> problem. 
> > Looking at it locally, the Gearman worker starts a transactions and just 
> > calls commit when the processing is done, over and over, never starting 
> a 
> > new transaction. That combined with REPEATABLE-READ seems to be the 
> culprit. 
> > 
> > My next step was going to be to set the isolation level to 
> READ-COMMITTED 
> > which would probably have fixed it as well.  Thought I'm not sure how 
> that 
> > would have affected performance. 
> > 
> > Will the changes to transactions in 1.6 possibly address this issue so I 
> > can remove the commit_unless_managed() call? It looks like the major 
> change 
> > is using the underlying database's autocommit mode rather than emulating 
> it 
> > in the ORM. I suppose I'll have to test... 
>
> The thing is Django didn't even emulate the autocommit mode in pre 1.6 
> versions. The behavior in 1.5 is this: 
>   1. Any query will start a transaction (unless of course you are 
> already in transaction) 
>   2. An ORM write will commit after the write is done (but not 
> rollback on exception!) 
>   3. Any other write will not commit 
>
> This is changed to: 
>   1. Any query will happen in autocommit mode - that is there are no 
> user-visible transactions. 
>   2. Some ORM write operations are wrapped in transaction (unless 
> already in transaction). Again, this is not user visible. Reason is 
> that for example multitable save() should be atomic. 
>
> That is, in 1.6 the mode is autocommit with some extra protection for 
> certain ORM write operations. 
>
> Another significant change: In pre 1.6 you can enter transaction block 
> by @commit_on_success. All queries inside the block will be part of 
> the same transaction. The name should be treated literally. If you 
> nest commit_on_success decorators you might get surprising behavior: 
> with commit_on_success: # Starts a transaction 
>     with commit_on_success: # Uses the same transaction 
>         obj.save() 
>     # Second commit_on_success commits on success. Note however that 
> the first commit_on_success started the transaction. 
>     otherobj.save() 
>     raise Exception("what happens?") 
>
> End situation is that obj.save() was committed, otherobj.save() 
> wasn't. A new transaction was started after the inner 
> commit_on_success block exited. In 99% of cases this isn't what was 
> wanted. 
>
> In 1.6 the code should be converted to: 
> with atomic: # Starts a transaction 
>     with atomic: # Creates a savepoint 
>         obj.save() 
>     # The savepoint is released 
>     otherobj.save() 
>     raise Exception 
>
> Now, the exception will cause a rollback of the transaction. Both obj 
> and otherobj save are rolled back. 
>
> All in all 1.6 transactions should be a lot easier to understand 
> (there isn't one unless you explicitly asked for a transaction), and 
> the atomic decorator is more powerful than commit_on_success. 
>
> I am not sure if you will need some form of commit in 1.6 before 
> the .get(). It depends on how the code is structured, and what does 
> start the problematic transaction. If the code uses some form of 
> explicit transaction control (commit_on_success, commit_manually) then 
> the autocommit behavior will not be in effect, and you will need 
> manual commit. If autocommit mode is in effect, things should just 
> work. 
>
>  - Anssi 
>

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


Reply via email to