In the previous installment,
I was wondering whether the tracking of snapshots could be made more
robust by having ActiveSnapshot be some sort of stack instead of a
global pointer. So I set to do that, and it turns out to appear a sane
thing to do. Here is a patch.
This is all kinda simple: whenever a piece of code wants ActiveSnapshot
to be set, instead of just assigning to it, it calls
PushActiveSnapshot(some-snap). When it's done with the snap, it calls
PopActiveSnapshot(). When some code needs to grab hold of the active
snapshot, we have GetActiveSnapshot() for it. There are also a couple
of places that need to know whether there currently is an active
snapshot; for those, we have ActiveSnapshotSet().
In practice this means we can get rid of several PG_TRY blocks that were
only concerned with "restoring" the previous value of ActiveSnapshot in
case of error: we now have snapmgr in charge of removing from the stack
all those snapshots that were set in the current subtransaction. For
all intents and purposes, this behaves the same as the old coding.
So, if you read the patch you'll notice that it's mostly about changing
ActiveSnapshot uses to either Push, Pop or GetActiveSnapshot. There are
a few extra hunks that deal with popping a snapshot just before
CommitTransactionCommand -- these are there because I decided that it is
a good idea to complain if someone pops a snapshot and then doesn't push
it. So things like VACUUM FULL, CREATE INDEX CONCURRENTLY and
multitable CLUSTER must deal with that internally. ISTM this is a sound
safety measure and it doesn't otherwise cause any other complication.
There is one place where the coding is a bit more involved:
_SPI_execute_plan is rather straightforward, _except_ that currently it
is being called with ActiveSnapshot = InvalidSnapshot -- and then we
call CopySnapshot(InvalidSnapshot). I'm not sure why this happens, but
in the meantime I've just made sure that we work around that and pass
InvalidSnapshot around as an explicit value instead of stealthly
creating copies of it.
The only disadvantage AFAICS is that there is a somewhat more palloc
traffic. I don't have numbers, but my guess is that the overall impact
Note: in the patch as attached, I removed some PG_TRY blocks and braces;
however, I did not reindent the contents of these blocks, in order to
keep the patch small.
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support