mirror of
https://github.com/postgres/postgres.git
synced 2025-07-15 19:21:59 +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:
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.136 2007/04/12 06:53:46 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.137 2007/11/30 21:22:53 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -562,7 +562,8 @@ AtCommit_Notify(void)
|
||||
*/
|
||||
result = heap_update(lRel, &lTuple->t_self, rTuple,
|
||||
&update_ctid, &update_xmax,
|
||||
GetCurrentCommandId(), InvalidSnapshot,
|
||||
GetCurrentCommandId(true),
|
||||
InvalidSnapshot,
|
||||
false /* no wait for commit */ );
|
||||
switch (result)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.288 2007/11/15 21:14:33 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.289 2007/11/30 21:22:53 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1033,7 +1033,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
|
||||
* which COPY can be invoked, I think it's OK, because the active
|
||||
* snapshot shouldn't be shared with anything else anyway.)
|
||||
*/
|
||||
ActiveSnapshot->curcid = GetCurrentCommandId();
|
||||
ActiveSnapshot->curcid = GetCurrentCommandId(false);
|
||||
|
||||
/* Create dest receiver for COPY OUT */
|
||||
dest = CreateDestReceiver(DestCopyOut, NULL);
|
||||
@ -1637,7 +1637,7 @@ CopyFrom(CopyState cstate)
|
||||
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
|
||||
MemoryContext oldcontext = CurrentMemoryContext;
|
||||
ErrorContextCallback errcontext;
|
||||
CommandId mycid = GetCurrentCommandId();
|
||||
CommandId mycid = GetCurrentCommandId(true);
|
||||
bool use_wal = true; /* by default, use WAL logging */
|
||||
bool use_fsm = true; /* by default, use FSM for free space */
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.167 2007/11/15 22:25:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.168 2007/11/30 21:22:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -233,7 +233,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
|
||||
* EXPLAIN can be invoked, I think it's OK, because the active snapshot
|
||||
* shouldn't be shared with anything else anyway.)
|
||||
*/
|
||||
ActiveSnapshot->curcid = GetCurrentCommandId();
|
||||
ActiveSnapshot->curcid = GetCurrentCommandId(false);
|
||||
|
||||
/* Create a QueryDesc requesting no output */
|
||||
queryDesc = CreateQueryDesc(plannedstmt,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.224 2007/11/16 01:51:22 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.225 2007/11/30 21:22:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -51,7 +51,6 @@ static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
|
||||
static HeapTuple GetTupleForTrigger(EState *estate,
|
||||
ResultRelInfo *relinfo,
|
||||
ItemPointer tid,
|
||||
CommandId cid,
|
||||
TupleTableSlot **newSlot);
|
||||
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
|
||||
int tgindx,
|
||||
@ -1801,8 +1800,7 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
|
||||
|
||||
bool
|
||||
ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
ItemPointer tupleid,
|
||||
CommandId cid)
|
||||
ItemPointer tupleid)
|
||||
{
|
||||
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
||||
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
||||
@ -1814,7 +1812,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
TupleTableSlot *newSlot;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
|
||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
|
||||
if (trigtuple == NULL)
|
||||
return false;
|
||||
|
||||
@ -1871,9 +1869,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
||||
{
|
||||
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
||||
tupleid,
|
||||
(CommandId) 0,
|
||||
NULL);
|
||||
tupleid, NULL);
|
||||
|
||||
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
|
||||
true, trigtuple, NULL);
|
||||
@ -1952,8 +1948,7 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
|
||||
|
||||
HeapTuple
|
||||
ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
ItemPointer tupleid, HeapTuple newtuple,
|
||||
CommandId cid)
|
||||
ItemPointer tupleid, HeapTuple newtuple)
|
||||
{
|
||||
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
||||
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
||||
@ -1965,7 +1960,7 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
TupleTableSlot *newSlot;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
|
||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
|
||||
if (trigtuple == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -2025,9 +2020,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
||||
{
|
||||
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
||||
tupleid,
|
||||
(CommandId) 0,
|
||||
NULL);
|
||||
tupleid, NULL);
|
||||
|
||||
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
|
||||
true, trigtuple, newtuple);
|
||||
@ -2038,7 +2031,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||
|
||||
static HeapTuple
|
||||
GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
|
||||
ItemPointer tid, CommandId cid,
|
||||
ItemPointer tid,
|
||||
TupleTableSlot **newSlot)
|
||||
{
|
||||
Relation relation = relinfo->ri_RelationDesc;
|
||||
@ -2060,7 +2053,8 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
|
||||
ltrmark:;
|
||||
tuple.t_self = *tid;
|
||||
test = heap_lock_tuple(relation, &tuple, &buffer,
|
||||
&update_ctid, &update_xmax, cid,
|
||||
&update_ctid, &update_xmax,
|
||||
estate->es_output_cid,
|
||||
LockTupleExclusive, false);
|
||||
switch (test)
|
||||
{
|
||||
@ -2086,8 +2080,7 @@ ltrmark:;
|
||||
epqslot = EvalPlanQual(estate,
|
||||
relinfo->ri_RangeTableIndex,
|
||||
&update_ctid,
|
||||
update_xmax,
|
||||
cid);
|
||||
update_xmax);
|
||||
if (!TupIsNull(epqslot))
|
||||
{
|
||||
*tid = update_ctid;
|
||||
|
Reference in New Issue
Block a user