Re: Lock-ups with multi-threading and psycopg 2.0.11

James Henstridge <[email protected]>
Newsgroups gmane.comp.python.db.psycopg.devel
Message-ID <[email protected]>
On Thu, Sep 24, 2009 at 12:01 AM, Richard Davies
<[email protected]> wrote:
>> > The database access is simple - I create a single connection centrally with:
> ...
>> > Whenever a thread needs to do an SQL query, it creates a cursor, does the
>> > query and destroys it. For example:
> ...
>> Note that if you're using the same connection for each thread, you
>> won't get much parallelism.  While one thread is executing a query,
>> all other threads will block if they try to do the same.  If you want
>> the threads to be able to issue queries in parallel, they will have to
>> use separate database connections.
>
> OK, that's interesting and not something which I'd realized. So I will
> probably change the code to separate connections for each thread.

When you consider that the normal usage pattern is to make use of
transactions, and transactions are managed at the connection level, it
makes sense.  The order that the queries get executed inside a
transaction matters, so having a system that gives non-deterministic
ordering would be a problem.

Now while you've disabled transaction support, the connection still
exhbits this behaviour.


>> > The section which typically locks up has the following code:
>> >
>> > ?logging.debug('1')
>> > ?cursor = db.cursor()
>> > ?logging.debug('2')
>> > ?cursor.execute('select "type", "resource", "usage", "user" from "resources"')
>> > ?logging.debug('3')
>> > ?rs = cursor.fetchall()
>> > ?logging.debug('4')
>> > ?cursor.execute('select "type", "resource", "key", "value" from "resource_properties"')
>> > ?logging.debug('5')
>> > ?ks = cursor.fetchall()
>> > ?logging.debug('6')
>> > ?cursor.close()
>> > ?logging.debug('7')
>> >
>> > In the logs, I see '1' and '2', but not '3' or anything later.
>> >
>> > Given that the lock-up is isolated to inside the cursor.execute(), it seems
>> > that it must be in psycopg? If that's the case, can you suggest a solution
>> > or how I can debug this further? For example, how (and where?) should I add
>> > trace inside the psycopg code to pinpoint this further?
>>
>> Is it possible that some other thread is performing a cursor.execute()
>> call and blocking the thread you are watching?
>
> It is definitely possible that I'm calling cursor.execute() twice in parallel
> for different cursors from different threads on the same connection.
>
> All of the SQL queries are very simple and should return immediately - they
> are selects or updates on a table with ~100 rows and ~5 columns.
>
> Is it meant to be thread-safe to execute cursor.execute() twice in parallel
> on different cursors of the same connection? Or could I have hit some
> deadlock/livelock in psycopg?

Quite possibly.  Psycopg performs locking of each connection so that
only one cursor can execute a statement at a time.  It is possible
that you've triggered a deadlock.  If you can provide a simple test
case that reproduces it, that would be quite helpful.


>> > I suspect that the problem may be having too many simultaneous open cursors.
>> > Is there a way that I can log how many of these there are? Where is the
>> > limit set, and can I raise it?
>
> Is this potentially a problem? It's quite plausible that I have ~100 cursors
> on the same single connection at present.
>
> I couldn't find any postgresql configuration or documentation relating to
> numbers of supported cursors - only max_connections.

Not likely.  The only resource extra cursors really take up is memory
on the application side to store the result set (this is assuming you
aren't using psycopg2's named cursor extension, in which case you'd be
allocating server side resources too).

James.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.