diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index 5580637..677db3a 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -538,7 +538,7 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) if (all_visible) { /* Don't pass rel; that will fail in recovery. */ - OldestXmin = GetOldestXmin(NULL, true); + OldestXmin = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM); } rel = relation_open(relid, AccessShareLock); @@ -660,7 +660,7 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) * a buffer lock. And this shouldn't happen often, so it's * worth being careful so as to avoid false positives. */ - RecomputedOldestXmin = GetOldestXmin(NULL, true); + RecomputedOldestXmin = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM); if (!TransactionIdPrecedes(OldestXmin, RecomputedOldestXmin)) record_corrupt_item(items, &tuple.t_self); diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index 8db1e20..46c167a 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -70,7 +70,7 @@ statapprox_heap(Relation rel, output_type *stat) TransactionId OldestXmin; uint64 misc_count = 0; - OldestXmin = GetOldestXmin(rel, true); + OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM); bstrategy = GetAccessStrategy(BAS_BULKREAD); nblocks = RelationGetNumberOfBlocks(rel); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 5016273..b5b8511 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -8845,7 +8845,7 @@ CreateCheckPoint(int flags) * StartupSUBTRANS hasn't been called yet. */ if (!RecoveryInProgress()) - TruncateSUBTRANS(GetOldestXmin(NULL, false)); + TruncateSUBTRANS(GetOldestXmin(NULL, PROCARRAY_FLAGS_DEFAULT)); /* Real work is done, but log and update stats before releasing lock. */ LogCheckpointEnd(false); @@ -9208,7 +9208,7 @@ CreateRestartPoint(int flags) * this because StartupSUBTRANS hasn't been called yet. */ if (EnableHotStandby) - TruncateSUBTRANS(GetOldestXmin(NULL, false)); + TruncateSUBTRANS(GetOldestXmin(NULL, PROCARRAY_FLAGS_DEFAULT)); /* Real work is done, but log and update before releasing lock. */ LogCheckpointEnd(true); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index f8d9214..0b0e73c 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2270,7 +2270,7 @@ IndexBuildHeapRangeScan(Relation heapRelation, { snapshot = SnapshotAny; /* okay to ignore lazy VACUUMs here */ - OldestXmin = GetOldestXmin(heapRelation, true); + OldestXmin = GetOldestXmin(heapRelation, PROCARRAY_FLAGS_VACUUM); } scan = heap_beginscan_strat(heapRelation, /* relation */ diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index ed3acb1..a19bd40 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -993,7 +993,7 @@ acquire_sample_rows(Relation onerel, int elevel, totalblocks = RelationGetNumberOfBlocks(onerel); /* Need a cutoff xmin for HeapTupleSatisfiesVacuum */ - OldestXmin = GetOldestXmin(onerel, true); + OldestXmin = GetOldestXmin(onerel, PROCARRAY_FLAGS_VACUUM); /* Prepare for sampling block numbers */ BlockSampler_Init(&bs, totalblocks, targrows, random()); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 812fb4a..c9c8209 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -497,7 +497,7 @@ vacuum_set_xid_limits(Relation rel, * always an independent transaction. */ *oldestXmin = - TransactionIdLimitedForOldSnapshots(GetOldestXmin(rel, true), rel); + TransactionIdLimitedForOldSnapshots(GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM), rel); Assert(TransactionIdIsNormal(*oldestXmin)); @@ -909,7 +909,7 @@ vac_update_datfrozenxid(void) * committed pg_class entries for new tables; see AddNewRelationTuple(). * So we cannot produce a wrong minimum by starting with this. */ - newFrozenXid = GetOldestXmin(NULL, true); + newFrozenXid = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM); /* * Similarly, initialize the MultiXact "min" with the value that would be diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 18d9d7e..31c567b 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -1221,7 +1221,7 @@ XLogWalRcvSendHSFeedback(bool immed) * everything else has been checked. */ if (hot_standby_feedback) - xmin = GetOldestXmin(NULL, false); + xmin = GetOldestXmin(NULL, PROCARRAY_FLAGS_DEFAULT); else xmin = InvalidTransactionId; diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index cd14667..f69a136 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -170,6 +170,7 @@ static void KnownAssignedXidsReset(void); static inline void ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact, TransactionId latestXid); static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid); +static int ConvertProcarrayFlagToProcFlag(int flags); /* * Report shared-memory space needed by CreateSharedProcArray. @@ -1252,6 +1253,22 @@ TransactionIdIsActive(TransactionId xid) return result; } +static int +ConvertProcarrayFlagToProcFlag(int flags) +{ + int result = 0; + + if (flags & PROCARRAY_A_FLAG_VACUUM) + result |= PROC_IN_VACUUM; + + if (flags & PROCARRAY_A_FLAG_ANALYZE) + result |= PROC_IN_ANALYZE; + + if (flags & PROCARRAY_A_FLAG_LOGICAL_DECODING) + result |= PROC_IN_LOGICAL_DECODING; + + return result; +} /* * GetOldestXmin -- returns oldest transaction that was running @@ -1260,8 +1277,9 @@ TransactionIdIsActive(TransactionId xid) * If rel is NULL or a shared relation, all backends are considered, otherwise * only backends running in this database are considered. * - * If ignoreVacuum is TRUE then backends with the PROC_IN_VACUUM flag set are - * ignored. + * Now, flags is used only for ignoring backends with some flags. Typically, + * if you want to ignore ones with PROC_IN_VACUUM flag, you can use + * PROCARRAY_FLAGS_VACUUM. * * This is used by VACUUM to decide which deleted tuples must be preserved in * the passed in table. For shared relations backends in all databases must be @@ -1302,16 +1320,19 @@ TransactionIdIsActive(TransactionId xid) * GetOldestXmin() move backwards, with no consequences for data integrity. */ TransactionId -GetOldestXmin(Relation rel, bool ignoreVacuum) +GetOldestXmin(Relation rel, int flags) { ProcArrayStruct *arrayP = procArray; TransactionId result; int index; bool allDbs; + int procFlags; volatile TransactionId replication_slot_xmin = InvalidTransactionId; volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId; + procFlags = ConvertProcarrayFlagToProcFlag(flags); + /* * If we're not computing a relation specific limit, or if a shared * relation has been passed in, backends in all databases have to be @@ -1340,14 +1361,7 @@ GetOldestXmin(Relation rel, bool ignoreVacuum) volatile PGPROC *proc = &allProcs[pgprocno]; volatile PGXACT *pgxact = &allPgXact[pgprocno]; - /* - * Backend is doing logical decoding which manages xmin separately, - * check below. - */ - if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING) - continue; - - if (ignoreVacuum && (pgxact->vacuumFlags & PROC_IN_VACUUM)) + if (pgxact->vacuumFlags & procFlags) continue; if (allDbs || diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index 9d5a13e..20dba6f 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -20,6 +20,18 @@ #include "utils/snapshot.h" +/* These are to implement PROCARRAY_FLAGS_XXX */ +#define PROCARRAY_A_FLAG_VACUUM 0x02 /* currently running lazy vacuum */ +#define PROCARRAY_A_FLAG_ANALYZE 0x04 /* currently running analyze */ +#define PROCARRAY_A_FLAG_LOGICAL_DECODING 0x10 /* currently doing logical + * decoding outside xact */ + +/* Use these flags in GetOldestXmin as "flags" */ +#define PROCARRAY_FLAGS_DEFAULT PROCARRAY_A_FLAG_LOGICAL_DECODING +#define PROCARRAY_FLAGS_VACUUM PROCARRAY_FLAGS_DEFAULT | PROCARRAY_A_FLAG_VACUUM +#define PROCARRAY_H_FLAGS_ANALYZE PROCARRAY_FLAGS_DEFAULT | PROCARRAY_A_FLAG_ANALYZE +#define PROCARRAY_FLAGS_VACUUM_ANALYZE PROCARRAY_FLAGS_DEFAULT | PROCARRAY_A_FLAG_VACUUM | PROCARRAY_A_FLAG_ANALYZE + extern Size ProcArrayShmemSize(void); extern void CreateSharedProcArray(void); extern void ProcArrayAdd(PGPROC *proc); @@ -53,7 +65,7 @@ extern RunningTransactions GetRunningTransactionData(void); extern bool TransactionIdIsInProgress(TransactionId xid); extern bool TransactionIdIsActive(TransactionId xid); -extern TransactionId GetOldestXmin(Relation rel, bool ignoreVacuum); +extern TransactionId GetOldestXmin(Relation rel, int flags); extern TransactionId GetOldestActiveTransactionId(void); extern TransactionId GetOldestSafeDecodingTransactionId(void);