summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorTom Lane2007-11-30 21:22:54 +0000
committerTom Lane2007-11-30 21:22:54 +0000
commit895a94de6dffa71741586a2228275f66db03f8ca (patch)
tree55ec3c2629305d83b35f98956c3c3bee449d86bb /src/backend/access
parentf0f18c7087e04a60e2612151401b07df87e51d96 (diff)
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.
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/heap/heapam.c8
-rw-r--r--src/backend/access/heap/tuptoaster.c4
-rw-r--r--src/backend/access/transam/xact.c67
3 files changed, 57 insertions, 22 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 20027592b50..1a4fc92f1c2 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.245 2007/11/15 21:14:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.246 2007/11/30 21:22:53 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1891,7 +1891,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
Oid
simple_heap_insert(Relation relation, HeapTuple tup)
{
- return heap_insert(relation, tup, GetCurrentCommandId(), true, true);
+ return heap_insert(relation, tup, GetCurrentCommandId(true), true, true);
}
/*
@@ -2174,7 +2174,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
result = heap_delete(relation, tid,
&update_ctid, &update_xmax,
- GetCurrentCommandId(), InvalidSnapshot,
+ GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */ );
switch (result)
{
@@ -2817,7 +2817,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
result = heap_update(relation, otid, tup,
&update_ctid, &update_xmax,
- GetCurrentCommandId(), InvalidSnapshot,
+ GetCurrentCommandId(true), InvalidSnapshot,
true /* wait for commit */ );
switch (result)
{
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 0a8873f9945..f26fa9f4a6b 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.79 2007/11/15 21:14:32 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.80 2007/11/30 21:22:53 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1086,7 +1086,7 @@ toast_save_datum(Relation rel, Datum value,
TupleDesc toasttupDesc;
Datum t_values[3];
bool t_isnull[3];
- CommandId mycid = GetCurrentCommandId();
+ CommandId mycid = GetCurrentCommandId(true);
struct varlena *result;
struct varatt_external toast_pointer;
struct
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 04804c38711..ce0dd812819 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -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;
+ /* 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();
+ }
/*
- * 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))));
}