Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 745c1b2

Browse files
committed
Rearrange vacuum-related bits in PGPROC as a bitmask, to better support
having several of them. Add two more flags: whether the process is executing an ANALYZE, and whether a vacuum is for Xid wraparound (which is obviously only set by autovacuum). Sneakily move the worker's recently-acquired PostAuthDelay to a more useful place.
1 parent 3ef1879 commit 745c1b2

File tree

7 files changed

+97
-41
lines changed

7 files changed

+97
-41
lines changed

src/backend/access/transam/twophase.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.36 2007/09/21 16:32:19 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.37 2007/10/24 20:55:36 alvherre Exp $
1111
*
1212
* NOTES
1313
* Each global transaction is associated with a global transaction
@@ -283,8 +283,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
283283
gxact->proc.databaseId = databaseid;
284284
gxact->proc.roleId = owner;
285285
gxact->proc.inCommit = false;
286-
gxact->proc.inVacuum = false;
287-
gxact->proc.isAutovacuum = false;
286+
gxact->proc.vacuumFlags = 0;
288287
gxact->proc.lwWaiting = false;
289288
gxact->proc.lwExclusive = false;
290289
gxact->proc.lwWaitLink = NULL;

src/backend/commands/analyze.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.109 2007/09/24 03:12:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.110 2007/10/24 20:55:36 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -31,6 +31,7 @@
3131
#include "parser/parse_relation.h"
3232
#include "pgstat.h"
3333
#include "postmaster/autovacuum.h"
34+
#include "storage/proc.h"
3435
#include "utils/acl.h"
3536
#include "utils/datum.h"
3637
#include "utils/lsyscache.h"
@@ -201,6 +202,11 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
201202
return;
202203
}
203204

205+
/* let others know what I'm doing */
206+
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
207+
MyProc->vacuumFlags |= PROC_IN_ANALYZE;
208+
LWLockRelease(ProcArrayLock);
209+
204210
/* measure elapsed time iff autovacuum logging requires it */
205211
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
206212
{
@@ -484,6 +490,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
484490
RelationGetRelationName(onerel),
485491
pg_rusage_show(&ru0))));
486492
}
493+
494+
/*
495+
* Reset my PGPROC flag. Note: we need this here, and not in vacuum_rel,
496+
* because the vacuum flag is cleared by the end-of-xact code.
497+
*/
498+
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
499+
MyProc->vacuumFlags &= ~PROC_IN_ANALYZE;
500+
LWLockRelease(ProcArrayLock);
487501
}
488502

489503
/*

src/backend/commands/vacuum.c

+10-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.359 2007/09/20 17:56:31 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.360 2007/10/24 20:55:36 alvherre Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -660,9 +660,9 @@ vacuum_set_xid_limits(int freeze_min_age, bool sharedRel,
660660
* fixed-size never-null columns, but these are.
661661
*
662662
* Another reason for doing it this way is that when we are in a lazy
663-
* VACUUM and have inVacuum set, we mustn't do any updates --- somebody
664-
* vacuuming pg_class might think they could delete a tuple marked with
665-
* xmin = our xid.
663+
* VACUUM and have PROC_IN_VACUUM set, we mustn't do any updates ---
664+
* somebody vacuuming pg_class might think they could delete a tuple
665+
* marked with xmin = our xid.
666666
*
667667
* This routine is shared by full VACUUM, lazy VACUUM, and stand-alone
668668
* ANALYZE.
@@ -987,22 +987,24 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
987987
* During a lazy VACUUM we do not run any user-supplied functions, and
988988
* so it should be safe to not create a transaction snapshot.
989989
*
990-
* We can furthermore set the inVacuum flag, which lets other
990+
* We can furthermore set the PROC_IN_VACUUM flag, which lets other
991991
* concurrent VACUUMs know that they can ignore this one while
992-
* determining their OldestXmin. (The reason we don't set inVacuum
992+
* determining their OldestXmin. (The reason we don't set it
993993
* during a full VACUUM is exactly that we may have to run user-
994994
* defined functions for functional indexes, and we want to make sure
995995
* that if they use the snapshot set above, any tuples it requires
996996
* can't get removed from other tables. An index function that
997997
* depends on the contents of other tables is arguably broken, but we
998998
* won't break it here by violating transaction semantics.)
999999
*
1000-
* Note: the inVacuum flag remains set until CommitTransaction or
1000+
* Note: this flag remains set until CommitTransaction or
10011001
* AbortTransaction. We don't want to clear it until we reset
10021002
* MyProc->xid/xmin, else OldestXmin might appear to go backwards,
10031003
* which is probably Not Good.
10041004
*/
1005-
MyProc->inVacuum = true;
1005+
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1006+
MyProc->vacuumFlags |= PROC_IN_VACUUM;
1007+
LWLockRelease(ProcArrayLock);
10061008
}
10071009

10081010
/*

src/backend/postmaster/autovacuum.c

+39-12
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
*
5656
*
5757
* IDENTIFICATION
58-
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.62 2007/10/24 19:08:25 alvherre Exp $
58+
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.63 2007/10/24 20:55:36 alvherre Exp $
5959
*
6060
*-------------------------------------------------------------------------
6161
*/
@@ -172,6 +172,7 @@ typedef struct autovac_table
172172
int at_freeze_min_age;
173173
int at_vacuum_cost_delay;
174174
int at_vacuum_cost_limit;
175+
bool at_wraparound;
175176
} autovac_table;
176177

177178
/*-------------
@@ -280,7 +281,7 @@ static autovac_table *table_recheck_autovac(Oid relid);
280281
static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
281282
Form_pg_class classForm,
282283
PgStat_StatTabEntry *tabentry, bool *dovacuum,
283-
bool *doanalyze);
284+
bool *doanalyze, bool *wraparound);
284285

285286
static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum,
286287
bool doanalyze, int freeze_min_age,
@@ -1440,9 +1441,6 @@ AutoVacWorkerMain(int argc, char *argv[])
14401441
/* Identify myself via ps */
14411442
init_ps_display("autovacuum worker process", "", "", "");
14421443

1443-
if (PostAuthDelay)
1444-
pg_usleep(PostAuthDelay * 1000000L);
1445-
14461444
SetProcessingMode(InitProcessing);
14471445

14481446
/*
@@ -1601,6 +1599,9 @@ AutoVacWorkerMain(int argc, char *argv[])
16011599
ereport(DEBUG1,
16021600
(errmsg("autovacuum: processing database \"%s\"", dbname)));
16031601

1602+
if (PostAuthDelay)
1603+
pg_usleep(PostAuthDelay * 1000000L);
1604+
16041605
/* And do an appropriate amount of work */
16051606
recentXid = ReadNewTransactionId();
16061607
do_autovacuum();
@@ -2085,6 +2086,14 @@ do_autovacuum(void)
20852086
/* clean up memory before each iteration */
20862087
MemoryContextResetAndDeleteChildren(PortalContext);
20872088

2089+
/* set the "vacuum for wraparound" flag in PGPROC */
2090+
if (tab->at_wraparound)
2091+
{
2092+
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2093+
MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
2094+
LWLockRelease(ProcArrayLock);
2095+
}
2096+
20882097
/*
20892098
* We will abort vacuuming the current table if something errors out,
20902099
* and continue with the next one in schedule; in particular, this
@@ -2119,6 +2128,7 @@ do_autovacuum(void)
21192128
get_rel_name(tab->at_relid));
21202129
EmitErrorReport();
21212130

2131+
/* this resets the PGPROC flags too */
21222132
AbortOutOfAnyTransaction();
21232133
FlushErrorState();
21242134
MemoryContextResetAndDeleteChildren(PortalContext);
@@ -2129,6 +2139,14 @@ do_autovacuum(void)
21292139
}
21302140
PG_END_TRY();
21312141

2142+
/* reset my PGPROC flag */
2143+
if (tab->at_wraparound)
2144+
{
2145+
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2146+
MyProc->vacuumFlags &= ~PROC_VACUUM_FOR_WRAPAROUND;
2147+
LWLockRelease(ProcArrayLock);
2148+
}
2149+
21322150
/* be tidy */
21332151
pfree(tab);
21342152

@@ -2223,9 +2241,10 @@ relation_check_autovac(Oid relid, Form_pg_class classForm,
22232241
{
22242242
bool dovacuum;
22252243
bool doanalyze;
2244+
bool dummy;
22262245

22272246
relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
2228-
&dovacuum, &doanalyze);
2247+
&dovacuum, &doanalyze, &dummy);
22292248

22302249
if (classForm->relkind == RELKIND_TOASTVALUE)
22312250
{
@@ -2272,6 +2291,8 @@ table_recheck_autovac(Oid relid)
22722291
bool doit = false;
22732292
PgStat_StatDBEntry *shared;
22742293
PgStat_StatDBEntry *dbentry;
2294+
bool wraparound,
2295+
toast_wraparound = false;
22752296

22762297
/* use fresh stats */
22772298
autovac_refresh_stats();
@@ -2298,7 +2319,7 @@ table_recheck_autovac(Oid relid)
22982319
shared, dbentry);
22992320

23002321
relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
2301-
&dovacuum, &doanalyze);
2322+
&dovacuum, &doanalyze, &wraparound);
23022323

23032324
/* OK, it needs vacuum by itself */
23042325
if (dovacuum)
@@ -2316,6 +2337,7 @@ table_recheck_autovac(Oid relid)
23162337
{
23172338
bool toast_dovacuum;
23182339
bool toast_doanalyze;
2340+
bool toast_wraparound;
23192341
Form_pg_class toastClassForm;
23202342
PgStat_StatTabEntry *toasttabentry;
23212343

@@ -2325,9 +2347,10 @@ table_recheck_autovac(Oid relid)
23252347
shared, dbentry);
23262348

23272349
/* note we use the pg_autovacuum entry for the main table */
2328-
relation_needs_vacanalyze(toastrelid, avForm, toastClassForm,
2329-
toasttabentry, &toast_dovacuum,
2330-
&toast_doanalyze);
2350+
relation_needs_vacanalyze(toastrelid, avForm,
2351+
toastClassForm, toasttabentry,
2352+
&toast_dovacuum, &toast_doanalyze,
2353+
&toast_wraparound);
23312354
/* we only consider VACUUM for toast tables */
23322355
if (toast_dovacuum)
23332356
{
@@ -2389,6 +2412,7 @@ table_recheck_autovac(Oid relid)
23892412
tab->at_freeze_min_age = freeze_min_age;
23902413
tab->at_vacuum_cost_limit = vac_cost_limit;
23912414
tab->at_vacuum_cost_delay = vac_cost_delay;
2415+
tab->at_wraparound = wraparound || toast_wraparound;
23922416
}
23932417

23942418
heap_close(avRel, AccessShareLock);
@@ -2403,7 +2427,8 @@ table_recheck_autovac(Oid relid)
24032427
* relation_needs_vacanalyze
24042428
*
24052429
* Check whether a relation needs to be vacuumed or analyzed; return each into
2406-
* "dovacuum" and "doanalyze", respectively. avForm and tabentry can be NULL,
2430+
* "dovacuum" and "doanalyze", respectively. Also return whether the vacuum is
2431+
* being forced because of Xid wraparound. avForm and tabentry can be NULL,
24072432
* classForm shouldn't.
24082433
*
24092434
* A table needs to be vacuumed if the number of dead tuples exceeds a
@@ -2437,7 +2462,8 @@ relation_needs_vacanalyze(Oid relid,
24372462
PgStat_StatTabEntry *tabentry,
24382463
/* output params below */
24392464
bool *dovacuum,
2440-
bool *doanalyze)
2465+
bool *doanalyze,
2466+
bool *wraparound)
24412467
{
24422468
bool force_vacuum;
24432469
float4 reltuples; /* pg_class.reltuples */
@@ -2499,6 +2525,7 @@ relation_needs_vacanalyze(Oid relid,
24992525
force_vacuum = (TransactionIdIsNormal(classForm->relfrozenxid) &&
25002526
TransactionIdPrecedes(classForm->relfrozenxid,
25012527
xidForceLimit));
2528+
*wraparound = force_vacuum;
25022529

25032530
/* User disabled it in pg_autovacuum? (But ignore if at risk) */
25042531
if (avForm && !avForm->enabled && !force_vacuum)

src/backend/storage/ipc/procarray.c

+14-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.35 2007/09/23 18:50:38 tgl Exp $
26+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.36 2007/10/24 20:55:36 alvherre Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -242,7 +242,8 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
242242
proc->xid = InvalidTransactionId;
243243
proc->lxid = InvalidLocalTransactionId;
244244
proc->xmin = InvalidTransactionId;
245-
proc->inVacuum = false; /* must be cleared with xid/xmin */
245+
/* must be cleared with xid/xmin: */
246+
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
246247
proc->inCommit = false; /* be sure this is cleared in abort */
247248

248249
/* Clear the subtransaction-XID cache too while holding the lock */
@@ -267,7 +268,8 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
267268

268269
proc->lxid = InvalidLocalTransactionId;
269270
proc->xmin = InvalidTransactionId;
270-
proc->inVacuum = false; /* must be cleared with xid/xmin */
271+
/* must be cleared with xid/xmin: */
272+
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
271273
proc->inCommit = false; /* be sure this is cleared in abort */
272274

273275
Assert(proc->subxids.nxids == 0);
@@ -296,8 +298,10 @@ ProcArrayClearTransaction(PGPROC *proc)
296298
proc->xid = InvalidTransactionId;
297299
proc->lxid = InvalidLocalTransactionId;
298300
proc->xmin = InvalidTransactionId;
299-
proc->inVacuum = false; /* redundant, but just in case */
300-
proc->inCommit = false; /* ditto */
301+
302+
/* redundant, but just in case */
303+
proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
304+
proc->inCommit = false;
301305

302306
/* Clear the subtransaction-XID cache too */
303307
proc->subxids.nxids = 0;
@@ -546,7 +550,8 @@ TransactionIdIsActive(TransactionId xid)
546550
* If allDbs is TRUE then all backends are considered; if allDbs is FALSE
547551
* then only backends running in my own database are considered.
548552
*
549-
* If ignoreVacuum is TRUE then backends with inVacuum set are ignored.
553+
* If ignoreVacuum is TRUE then backends with the PROC_IN_VACUUM flag set are
554+
* ignored.
550555
*
551556
* This is used by VACUUM to decide which deleted tuples must be preserved
552557
* in a table. allDbs = TRUE is needed for shared relations, but allDbs =
@@ -586,7 +591,7 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
586591
{
587592
volatile PGPROC *proc = arrayP->procs[index];
588593

589-
if (ignoreVacuum && proc->inVacuum)
594+
if (ignoreVacuum && (proc->vacuumFlags & PROC_IN_VACUUM))
590595
continue;
591596

592597
if (allDbs || proc->databaseId == MyDatabaseId)
@@ -723,7 +728,7 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
723728
TransactionId xid;
724729

725730
/* Ignore procs running LAZY VACUUM */
726-
if (proc->inVacuum)
731+
if (proc->vacuumFlags & PROC_IN_VACUUM)
727732
continue;
728733

729734
/* Update globalxmin to be the smallest valid xmin */
@@ -1193,7 +1198,7 @@ CheckOtherDBBackends(Oid databaseId)
11931198

11941199
found = true;
11951200

1196-
if (proc->isAutovacuum)
1201+
if (proc->vacuumFlags & PROC_IS_AUTOVACUUM)
11971202
{
11981203
/* an autovacuum --- send it SIGTERM before sleeping */
11991204
int autopid = proc->pid;

src/backend/storage/lmgr/proc.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.194 2007/09/08 20:31:15 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.195 2007/10/24 20:55:36 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -291,8 +291,9 @@ InitProcess(void)
291291
MyProc->databaseId = InvalidOid;
292292
MyProc->roleId = InvalidOid;
293293
MyProc->inCommit = false;
294-
MyProc->inVacuum = false;
295-
MyProc->isAutovacuum = IsAutoVacuumWorkerProcess();
294+
MyProc->vacuumFlags = 0;
295+
if (IsAutoVacuumWorkerProcess())
296+
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
296297
MyProc->lwWaiting = false;
297298
MyProc->lwExclusive = false;
298299
MyProc->lwWaitLink = NULL;
@@ -429,8 +430,8 @@ InitAuxiliaryProcess(void)
429430
MyProc->databaseId = InvalidOid;
430431
MyProc->roleId = InvalidOid;
431432
MyProc->inCommit = false;
432-
MyProc->inVacuum = false;
433-
MyProc->isAutovacuum = IsAutoVacuumLauncherProcess(); /* is this needed? */
433+
/* we don't set the "is autovacuum" flag in the launcher */
434+
MyProc->vacuumFlags = 0;
434435
MyProc->lwWaiting = false;
435436
MyProc->lwExclusive = false;
436437
MyProc->lwWaitLink = NULL;

0 commit comments

Comments
 (0)