Prepared Transactions
James William Pye
pgsql at jwp.name
Sat Jan 19 18:28:15 UTC 2008
Per a recent thread that I saw on DB-SIG, I realized that I had completely
forgotten about prepared transactions; certainly this is something that needs to
be covered soon, so I started to think of what should be done with the current
transaction manager to accomplish some aspects of this..
ISTM that there are two distinct components that must be managed
separately--surely obvious, the initial prepare and the final commit or
rollback. The initial prepare can and should be handled using the existing
manager:
with gtx.xact('xid'):
...
or:
gtx.xact('xid')
with gtx.xact:
...
That is, if a transaction is configured as being "identified", the
transaction manager will issue a "PREPARE TRANSACTION '%(gid)s'" instead of the
standard commit. Very simple and very handy.
The one problem with this is that alone it requires some redundancy for simple
2PC applications:
with nested(
gtx1.xact('xid'),
gtx2.xact('xid'),
):
...
But notably, there is a potential need for solitude, so I think that having this
as a starting point for prepared transactions *is* good.
That leaves managing final commits and rollbacks, so I think simply adding two
methods to gtx.xact would suffice for basic interface:
class xact(object):
...
def commit_prepared(self, gid):
...
def rollback_prepared(self, gid):
...
...
Arguably, the connection is just as good of a place for these methods to exist.
However, the connection's transaction manager seems apt.
And finally, other than something that provides with statement support for a
set of transactions, I'm not sure what else should be done:
class xactset(object):
def __init__(self, gid, *cset):
self.gid = gid
self.cset = cset
def __context__(self):
return self
def __enter__(self):
for c in cset:
c.xact(self.gid)
def __exit__(self, typ, ob, tb):
if typ is None:
for c in cset:
c.xact.commit_prepared(self.gid)
else:
for c in cset:
c.xact.rollback_prepared(self.gid)
with xactset(
'gid',
gtx1, gtx2, ..., gtxn
):
...
However, I'm really unsure where something like this should exist. =\
I guess the greentrunk package would be appropriate enough, but that doesn't
seem particularly convenient:
>>> from postgresql.protocol.greentrunk.transactions import xactset
These are features that will make it into 1.0.
Thoughts?
More information about the Python-general
mailing list