>Since our system went live we have been getting more & more errors
>like this: "DBAPIError: (Error) ('HY000', '[HY000] [Microsoft][SQL
>Native Client]Connection is busy with results for another command
>(0)') u'SELECT" ...snip valid SQL string...endsnip
>
>
I've seen this error too, in fact some of the unit tests trigger it. The
cause is that a single ODBC connection can only have one query active at
a time, even if you have multiple cursors. I believe this is different
to most other DBAPI drivers.
I have no idea how to fix this in SQLAlchemy, have thought about it a
bit without success. A workaround is to recode your app to it fetches
results right after each query.
Paul
we used to have a feature on the Pool called "auto_close_cursors" -
this would track all open cursors at the pool level, and when a
connection is re-checked in would close them all. In reality, this
feature was in most cases just hiding opened cursors that should have
been closed at higher levels, and added a lot of latency at a crucial
point in execution. So in modern SQLAlchemy, cursors are closed
automatically when: 1. the statement is a non-row returning statement
like INSERT, UPDATE, etc. 2. all result rows are exhausted from a
result. (When the ORM is used, result rows are always fully exhausted
unless the "yield_per" Query option is used). So if you are using
straight connection or engine result sets, and are not explicitly
exhausting all rows, call result.close() to explicitly release the
cursor. That will solve the problem.
>
> Hi Michael,
>
> Thanks for your persistence :)
>
> I've searched through my app, & we don't seem to have any calls to
> fetchone(), so I'm not sure what else to look for, but I'll try to do
> some debugging with ResultProxys, & see if that leads to any possible
> answers.
>
> On a side note, in our Pylons development.ini, we have these settings:
> sqlalchemy.default.max_overflow = -1
> sqlalchemy.default.pool_size = 32
>
> Is there anything there that could be having an effect on this?
well, try sending along a stack trace when you catch it
happening....what conditions seem to correlate with its occurence ?
does it appear to be related to a high degree of concurrent
activity ? the max_overflow means the pool has no limit to how many
connections it can open in response to requests.
>
> Just a side note, is the pool code thread safe?
> i.e. no two threads would possibly checkout the same connection at any
> point in time?
we're pretty confident its completely threadsafe as of 0.3.11, we have
several different kinds of tests for its thread-safety now and we
havent heard of anyone having these kinds of issues on the "thread-
sensitive" DBAPIs like MySQLDB in a long time.
What my suspicion here is, is that the connection is being returned to
the pool and properly being checked out elsewhere (even in the same
thread), but theres a cursor still opened somewhere. As I've
mentioned, we removed the "check for any remaining open cursors" logic
a while back since its not needed in most cases, since the ResultProxy
automatically closes cursors in all cases except when SELECT results
are pending (and in that case the end-user should be closing the
result set or fetching all results) - in that case, the cursor still
gets closed when the resultproxy is garbage collected but garbage
collection is not always immediate, even with an object such as RP
which intentionally does not have circular references for this reason.
What I'm not sure of at this point is if theres some cursor usage
specific to the MS-SQL dialect that might be external to the
ResultProxy....if Rick could comb through that for me that would be
helpful.
Yeah, I see that its used. But no new cursor is opened, so this
doesnt seem like it could be involved.
It is possible we could re-introduce "check for open cursors" as a
pool events extension. It would raise an error if any connection is
returned with associated cursors still opened and could track down
issues like these.
It is possible we could re-introduce "check for open cursors" as a
pool events extension. It would raise an error if any connection is
returned with associated cursors still opened and could track down
issues like these.
>
> I don't know whether this helps, but many thanks for looking at the
> issue :)
unfortunately it doesnt say much at all. You're not sharing a Session
between multiple threads, right ?
and by "sharing", I mean the Session, as well as any objects that are
attached to it, since that stack trace illustrated specifically an
attribute lazy-loading its contents from the database.
>
> We're not intentionally sharing a session between multiple
> threads... :) I'll check out the code to see if there is any sharing
> going on, but I'm pretty sure that's not the case.
>
> You mention lazy-loading as if it might be playing a part in this
> issue - is that right? We are using lazy & eager loading in various
> parts of the app...
the lazy loading can present an issue only to the degree that the
object still maintains a link to its originating Session. So if the
lazy loader fires off in a thread other than that where the Session
normally resides, you can have concurrent access to it, which in the
case of the Session already being within a transaction, could create
concurrent access on a single connection.
Basically if you dont share anything between threads, in theory this
kind of issue should not occur.