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.

