psycopg, transactions and multiple cursors
Steve Holden
steve at holdenweb.com
Tue Nov 9 08:26:43 EST 2004
Alban Hertroys wrote:
> Diez B. Roggisch wrote:
>
>>> AFAIK, you can't open a transaction w/o using a cursor; You need a query
>>> that says "BEGIN;".
>>> You can commit a connection object, however. It would be nice to be able
>>> to start a transaction on a connection object, but then you still could
>>> only have one transaction per connection... :(
>>
>>
>>
>> thats actually the case for all DBs I know including e.g. oracle with
>> jdbc -
>> so the abstraction layers usually use connection pooling to speed up
>> opening a connection thus the app doesn't suffer so much.
>
Yes, most database connections will generate an implicit transaction the
first time a change is made to the database (in the absence of autocommit).
>
> Ok, that means I won't get away with a single connection object (unless
> psycopg puts a connection pool in a single connection object).
>
>> No idea why thats happening - on jdbc, one can set an "autocommit"
>> connection property that will do exactly that: enforce a commit if a
>> statement was successful. Maybe psycopg has that too?
>
>
> Yes, it does have autoCommit, and thankfully it can be turned off (which
> I did, of course).
>
It certainly isn't too useful if you occasionally need to roll things
back. Structural changes to the database will frequently cause an
automatic commit anyway, though - you aren't modifying the database
structure at all, I take it?
>>> I know PostgreSQL can do transactions on nested cursors, I have used
>>> that now and then in stored procedures (pl/pgsql).
>
>
>> I didn't find much on nested cursors on google, so I don't know how they
>> work - but I assume if they are part of psycopg, they somehow have to be
>> created using an existing cursor, as otherwise how should psycopg know
>> that
>> what you want is a nested and not a new cursor.
>
>
> Actually, nesting of cursors is something that PL/PgSQL can do. And so
> can PL/SQL in Oracle.
> It's something that's possible on a low database API level, and (to my
> understanding) the DBAPI 2.0 uses them for queries. It's one of Pythons'
> advantages over eg. PHP, and one of the reasons I chose to use Python
> for this project.
>
Nested cursors aren;t nested transcations, though, right?
>> So is there something on cursor objecst to get a new cursor, or at
>> least the
>> connection so you can get a cursor on the very same connection?
>
>
> A cursor is comparable to an iterator over a result set (where the
> cursor fetches one record from the database at a time).
>
B e careful that you don;t confuse the DB API curosrs with the cursors
you get with DECLARE CURSOR in PL/SQL, for example. The two aren;t
necessarily the same thing (and I've always felt that "cursor" was, for
that reason, not the best possible terminological choice for the DB API).
> You use one for every query, and it can often be reused for the next
> query as well.
>
> However, if you loop through a result set (with a cursor) and you need
> to do a query based on the record that the cursor is currently
> positioned at, you can't use the same cursor again for that query, but
> need to open a new cursor. That's what I meant by "nesting cursors".
>
Bear in mind, though, that it will often be *much* more efficient to do
a fetchall() from the cursor and iterate over that result. This
typically avoids many round-trips by fetching all the data at once,
though it's less practical if data sets become huge.
There's sometimes a middle ground to be found with repeated calls to
fetchmany().
In that way the curosr can be reused with impunity once the data has
been fetched.
> That shouldn't matter for the state of a transaction, though...
>
> Maybe there's a difference between database level cursors and DB API 2.0
> level cursors in Python?
>
As I mentioned above, there often is.
I think we've already agreed that the psycopg cursors aren't DB API
compliant anyway, precisely because of the way they handle transactions.
An API-compliant library shares transaction state across all cursors
generated from the same connection, which (IMHO) gives the flexibility
one needs to to handle complex database interactions.
> The number of questions is increasing...
Well, the number of answers is, too, but it seems to me you *are* kind
of wanting to have your cake and eat it. In previous threads you've
suggested that the psycopg cursor behavior is what you want, but now
that very behavior might (?) be biting you.
Anyway, you couldn't be talking to a better bunch of guys to try and
solve this problem. c.l.py is sometimes persistent beyond all reasonable
limits. Good luck!
regards
Steve
--
http://www.holdenweb.com
http://pydish.holdenweb.com
Holden Web LLC +1 800 494 3119
More information about the Python-list
mailing list