[mod_python] Custom handler thread safety

Graham Dumpleton grahamd at dscpl.com.au
Fri Feb 4 23:38:43 EST 2005


I'll try and get back to your original problem. I probably digressed
and certainly said some things already that most likely aren't relevant
at all. I should have perhaps read the email properly. My excuse is that
I was having a busy day that day. :-)

On 05/02/2005, at 6:56 AM, Huzaifa Tapal wrote:
>> Is the Python database connection object internally thread safe?
>
> -- not its not.

I should have phrased this question a bit better. Does the database
interface code support having multiple connection objects active at
the same time, where each may be held by a distinct thread with that
thread doing whatever it wants with its own connection object?

Thus, a single database connection object doesn't necessarily have
to be thread safe in itself, as long as there can be multiple connection
objects each being used at the same time by different threads.

Anyway, in your original email you said:

   Just to be safe, I implemented thread locking into the handler
   before any request is processed.

That to me says what you did was to make sure only one request at a
time could actually do anything. Thus all requests were serialised.
If this was the case, you wouldn't have had any thread problems because
there wouldn't have actually been multiple requests active, a latter
request would have sat there until the previous one finished.

If this is true, using a multithreaded MPM would also have just made
things worse. You would have been better of using Apache in "prefork"
mode as then each request in each process could have at least run in
parallel.

Next you said:

   We are gaining huge performance increases by caching our template
   objects and db connection objects.

Which is logical, as you have avoided the startup cost with creating
a database connection for each request, as well as the cost of loading
a template on every request. This would be true whether or not you are
using threads.

Your next comment was:

   The problem I am running into is that if I run through the 
application,
   each request takes on average 300 ms to process.  However, when we
   benchmark with 20 concurrent users, the average goes up to around
   2200 ms.  I am very sure that this is due to a thread locking
   shared objects in memory which results in another thread waiting for
   the lock to be released.

If each thread was trying to acquire the same lock before going into a
handler and only releasing it when exiting the handler, thus serialising
requests, what you are seeing would be expected. In short you were
simply overloading your servers ability to respond quickly enough. Add
even more concurrent users and the average would like keep growing.

Finally you said:

   If I take the thread locking mechanism out then we run into problems
   with there being too many connections being made to the MySQL db if
   the cached connection is being used and then the db starts dropping
   connections.

If there was indeed a lock around any handler call and you took it out,
you would at least still need to thread protect your database connection
pool/cache.

You might need to explain how you manage your database connections.

I haven't done database connection pooling in mod_python when using
threads yet but there are others here who have and may suggest the best 
ways
of doing it.

To me the simplest way would be to create a set of database connection
objects at startup and place these in a Queue.Queue object. As each 
request
comes in, it can get an available database connection off the queue,
use it then put it back. In practice, it probably needs to be a bit more
robust than that.

Anyway, confirm exactly what you meant by having thread locking going
into the handler and describe how you are managing the database
connections. Do you create a certain number of database connections at
startup, or on demand as required, but only up to a certain maximum?
Is your connection caching mechanism thread protected in any way?

Sorry again for getting off the track. :-)

Graham




More information about the Mod_python mailing list