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 <[email protected]> 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 [email protected].
To post to this group, send email to [email protected].
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