> On Nov 28, 2014, at 9:28 AM, Guido Winkelmann 
> <gu...@ambient-entertainment.de> wrote:
> 
> Hi,
> 
> What's the best strategy for retrying failed transactions when using 
> SQLAlchemy?
> 
> Sometimes, transactions fail on commit, through no fault of their own, simply 
> because another concurrent but conflicting transaction finished slightly 
> before them. The commonly accepted best practice  seems to be that you should 
> just retry your transaction – including all client side logic – in such cases 
> until it succeeds (or until you run into some timeout).
> 

This is the best practice.  To encapsulate the full series of operations you’re 
doing in the transaction into a Python function, which you then invoke under a 
so-called “retry” decorator.  This decorator runs the function, catches the SQL 
errors that you deem as appropriate for a “retry”, then it invokes the whole 
function again.  It typically does this for up to a certain number of times 
before giving up completely and re-raising the exception.


> The problem is, in SQLAlchemy, at least with a PostgreSQL+psycopg2 backend, 
> the exception I get when that happens is "InvalidRequestError". This is not 
> very helpful, as I cannot tell the difference between a genuinely invalid 
> request and a mere transaction failure like this. I also don't know if the 
> exception will be different on different backends.

then that means you’re doing something incorrectly.   The actual message of 
this exception as well as a stack trace and concise and self-contained examples 
of code would allow us to have some idea what this might be.  
InvalidRequestError is also a SQLAlchemy-generated exception, not a DBAPI 
error, so will be identical on all backends.

> After some experimentation and research, it turned out that the root cause 
> here was that PostgreSQL's default transaction isolation level of "read 
> committed" was just not enough in my case, and I would need to increase it to 
> "serializable”.

that is also suspect.  serializable isolation is very tough to use due to the 
high degree of locking and it suggests there is some level of concurrency here 
that is probably better accommodated using either a correctly implemented 
optimistic approach (e.g. the retry) or if UPDATES are part of the issue, 
SELECT..FOR UPDATE can often help to lock rows ahead of time when updates will 
be needed.


> Doing that, however, led to a rude awakening for me regarding handling of 
> failed transactions. They suddenly turned from something mostly theoretical, 
> that I know about but could safely ignore in practice almost all of the time, 
> into a very real thing that happens a lot in practice and that I need to deal 
> with somehow, because otherwise my application pretty much ceases to work for 
> all practical purposes.

feel free to share more specifics as long as they are concise and 
self-contained.

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

Reply via email to