Re: Fwd: [Zope] Using psycopg connections directly
Scavenging the mail folder uncovered Paolo Comitini's letter:
Because psycopg is advertised as having a per-cursor commits, initially I just did the same thing in my code as a Z SQL Method would do: call the database object for a connection and run query() on it. However, it turned out that when multiple threads did this, one thread's commit would also commit work on another thread. This is probably due to the fact that the psycopg DB class commits on the connection, not on the cursor it used.
if you want to use the per-cursor commit extension of psycopg, you need to call the .commit() method on the *cursor*. calling it on the connection will commit on all the cursors derived from the connection.
So I now grab a cursor, and register that (inside a wrapper) with the transaction manager, for every query. The finish/abort code does a commit/rollback and then a cursor.close() (shortly after that, the GC destroys the cursor). However, I seem to be leaking connections, because the number of in-use connections quickly goes up and Postgres starts complaining. There's probably some interaction between what I do and psycopg that I don't understand.
note that psycopg open one connection for every cursor (that will change in the near future) so, if you don't set a maxconn value on the connection but keep creating cursors, you'll finish with an hight number of phisical db connections (maxconn is about 32 by default.)
Would anyone have a suggestion as to how I could use psycopg Z Database connections from Python code in such a way that everything works smoothly? What's the Zope model anyway - does it instantiate one Z connection per thread or do all the threads use the same connection and should the connection figure it out by itself?
mmm... i think that zope instantiate a connection for every thread. in the psycopg case, every zope thread gets one connection and one cursor. hope this helps, ciao, federico -- Federico Di Gregorio MIXAD LIVE Chief of Research & Technology fog@mixadlive.com Debian GNU/Linux Developer & Italian Press Contact fog@debian.org Qu'est ce que la folie? Juste un sentiment de liberté si fort qu'on en oublie ce qui nous rattache au monde... -- J. de Loctra
fog@mixadlive.com said:
if you want to use the per-cursor commit extension of psycopg, you need to call the .commit() method on the *cursor*. calling it on the connection will commit on all the cursors derived from the connection.
I know (I wrote ODBC drivers for a living, among others a PostgreSQL one :-)). I sorta expected the Z SQL Connection to do the "right thing", but it forwards the TM messages to the connection, not to individual cursors.
mmm... i think that zope instantiate a connection for every thread. in the psycopg case, every zope thread gets one connection and one cursor.
Let's hope so, although I haven't been able to discern the code that does that bit of magic. Is there a document somewhere that describes what Zope does, thread-wise, when handling requests? Anyway, I plunged into my code and FYI, this is how I'm now dealing with it: - select statements grab and release a cursor; - update statements grab a cursor, wrap them in a TM subclass and register the result with the transaction manager. The cursor is also registered in a thread map, so that subsequent update statements in the same thread/transaction reuse the cursor. When the Zope TM calls finish()/abort(), the cursor is committed and released (and removed from the thread map). - session access (updating the "last accessed" timestamp on mostly every request) is done through a special global cursor, which does a commit every 10 or so updates keeping disk write load for this non-critical piece of information low. The end result is acceptably low connection usage and correct transaction scoping. Now I only have to find that (*&@#$ deadlock somewhere in my code ;-). -- Cees de Groot http://www.cdegroot.com <cg@cdegroot.com> GnuPG 1024D/E0989E8B 0016 F679 F38D 5946 4ECD 1986 F303 937F E098 9E8B -- Cees de Groot http://www.cdegroot.com <cg@cdegroot.com> GnuPG 1024D/E0989E8B 0016 F679 F38D 5946 4ECD 1986 F303 937F E098 9E8B
participants (2)
-
cg@cdegroot.com -
Federico Di Gregorio