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:
@ -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))));
|
||||
}
|
||||
|
Reference in New Issue
Block a user