1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Avoid incrementing the CommandCounter when CommandCounterIncrement is called

but no database changes have been made since the last CommandCounterIncrement.
This should result in a significant improvement in the number of "commands"
that can typically be performed within a transaction before hitting the 2^32
CommandId size limit.  In particular this buys back (and more) the possible
adverse consequences of my previous patch to fix plan caching behavior.

The implementation requires tracking whether the current CommandCounter
value has been "used" to mark any tuples.  CommandCounter values stored into
snapshots are presumed not to be used for this purpose.  This requires some
small executor changes, since the executor used to conflate the curcid of
the snapshot it was using with the command ID to mark output tuples with.
Separating these concepts allows some small simplifications in executor APIs.

Something for the TODO list: look into having CommandCounterIncrement not do
AcceptInvalidationMessages.  It seems fairly bogus to be doing it there,
but exactly where to do it instead isn't clear, and I'm disinclined to mess
with asynchronous behavior during late beta.
This commit is contained in:
Tom Lane
2007-11-30 21:22:54 +00:00
parent f0f18c7087
commit 895a94de6d
20 changed files with 217 additions and 252 deletions

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.253 2007/11/15 21:14:32 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.254 2007/11/30 21:22:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -161,6 +161,7 @@ static TransactionState CurrentTransactionState = &TopTransactionStateData;
*/
static SubTransactionId currentSubTransactionId;
static CommandId currentCommandId;
static bool currentCommandIdUsed;
/*
* xactStartTimestamp is the value of transaction_timestamp().
@ -435,11 +436,18 @@ GetCurrentSubTransactionId(void)
/*
* GetCurrentCommandId
*
* "used" must be TRUE if the caller intends to use the command ID to mark
* inserted/updated/deleted tuples. FALSE means the ID is being fetched
* for read-only purposes (ie, as a snapshot validity cutoff). See
* CommandCounterIncrement() for discussion.
*/
CommandId
GetCurrentCommandId(void)
GetCurrentCommandId(bool used)
{
/* this is global to a transaction, not subtransaction-local */
if (used)
currentCommandIdUsed = true;
return currentCommandId;
}
@ -566,25 +574,50 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
void
CommandCounterIncrement(void)
{
currentCommandId += 1;
if (currentCommandId == FirstCommandId) /* check for overflow */
/*
* If the current value of the command counter hasn't been "used" to
* mark tuples, we need not increment it, since there's no need to
* distinguish a read-only command from others. This helps postpone
* command counter overflow, and keeps no-op CommandCounterIncrement
* operations cheap.
*/
if (currentCommandIdUsed)
{
currentCommandId -= 1;
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
currentCommandId += 1;
if (currentCommandId == FirstCommandId) /* check for overflow */
{
currentCommandId -= 1;
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot have more than 2^32-1 commands in a transaction")));
}
currentCommandIdUsed = false;
/* Propagate new command ID into static snapshots, if set */
if (SerializableSnapshot)
SerializableSnapshot->curcid = currentCommandId;
if (LatestSnapshot)
LatestSnapshot->curcid = currentCommandId;
/*
* Make any catalog changes done by the just-completed command
* visible in the local syscache. We obviously don't need to do
* this after a read-only command. (But see hacks in inval.c
* to make real sure we don't think a command that queued inval
* messages was read-only.)
*/
AtCommit_LocalCache();
}
/* Propagate new command ID into static snapshots, if set */
if (SerializableSnapshot)
SerializableSnapshot->curcid = currentCommandId;
if (LatestSnapshot)
LatestSnapshot->curcid = currentCommandId;
/*
* make cache changes visible to me.
* Make any other backends' catalog changes visible to me.
*
* XXX this is probably in the wrong place: CommandCounterIncrement
* should be purely a local operation, most likely. However fooling
* with this will affect asynchronous cross-backend interactions,
* which doesn't seem like a wise thing to do in late beta, so save
* improving this for another day - tgl 2007-11-30
*/
AtCommit_LocalCache();
AtStart_Cache();
}
@ -1416,6 +1449,7 @@ StartTransaction(void)
s->subTransactionId = TopSubTransactionId;
currentSubTransactionId = TopSubTransactionId;
currentCommandId = FirstCommandId;
currentCommandIdUsed = false;
/*
* must initialize resource-management stuff first
@ -4007,13 +4041,14 @@ ShowTransactionStateRec(TransactionState s)
/* use ereport to suppress computation if msg will not be printed */
ereport(DEBUG3,
(errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
(errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
PointerIsValid(s->name) ? s->name : "unnamed",
BlockStateAsString(s->blockState),
TransStateAsString(s->state),
(unsigned int) s->transactionId,
(unsigned int) s->subTransactionId,
(unsigned int) currentCommandId,
currentCommandIdUsed ? " (used)" : "",
s->nestingLevel,
nodeToString(s->childXids))));
}