From adc4e1e6353bfda442c23a32f172eb42c649c495 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 14 Mar 2008 17:25:59 +0000 Subject: [PATCH] Fix vacuum so that autovacuum is really not cancelled when doing an emergency job (i.e. to prevent Xid wraparound problems.) Bug reported by ITAGAKI Takahiro in 20080314103837.63D3.52131E4D@oss.ntt.co.jp, though I didn't use his patch. --- src/backend/commands/vacuum.c | 23 +++++++++++++++++------ src/backend/postmaster/autovacuum.c | 16 +++++----------- src/backend/tcop/utility.c | 4 ++-- src/include/commands/vacuum.h | 4 ++-- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index a073a1d68e..72a50690ba 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.366 2008/03/10 02:04:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.367 2008/03/14 17:25:58 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -209,7 +209,8 @@ static BufferAccessStrategy vac_strategy; static List *get_rel_oids(List *relids, const RangeVar *vacrel, const char *stmttype); static void vac_truncate_clog(TransactionId frozenXID); -static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind); +static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind, + bool for_wraparound); static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); static void scan_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages); @@ -263,6 +264,9 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page); * relation OIDs to be processed, and vacstmt->relation is ignored. * (The non-NIL case is currently only used by autovacuum.) * + * for_wraparound is used by autovacuum to let us know when it's forcing + * a vacuum for wraparound, which should not be auto-cancelled. + * * bstrategy is normally given as NULL, but in autovacuum it can be passed * in to use the same buffer strategy object across multiple vacuum() calls. * @@ -274,7 +278,7 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page); */ void vacuum(VacuumStmt *vacstmt, List *relids, - BufferAccessStrategy bstrategy, bool isTopLevel) + BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel) { const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; volatile MemoryContext anl_context = NULL; @@ -421,7 +425,7 @@ vacuum(VacuumStmt *vacstmt, List *relids, Oid relid = lfirst_oid(cur); if (vacstmt->vacuum) - vacuum_rel(relid, vacstmt, RELKIND_RELATION); + vacuum_rel(relid, vacstmt, RELKIND_RELATION, for_wraparound); if (vacstmt->analyze) { @@ -966,7 +970,8 @@ vac_truncate_clog(TransactionId frozenXID) * At entry and exit, we are not inside a transaction. */ static void -vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) +vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind, + bool for_wraparound) { LOCKMODE lmode; Relation onerel; @@ -999,6 +1004,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) * contents of other tables is arguably broken, but we won't break it * here by violating transaction semantics.) * + * We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down + * by autovacuum; it's used to avoid cancelling a vacuum that was + * invoked in an emergency. + * * Note: this flag remains set until CommitTransaction or * AbortTransaction. We don't want to clear it until we reset * MyProc->xid/xmin, else OldestXmin might appear to go backwards, @@ -1006,6 +1015,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->vacuumFlags |= PROC_IN_VACUUM; + if (for_wraparound) + MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND; LWLockRelease(ProcArrayLock); } @@ -1147,7 +1158,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) * totally unimportant for toast relations. */ if (toast_relid != InvalidOid) - vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE); + vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE, for_wraparound); /* * Now release the session-level lock on the master table. diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 9175f65a52..ca0bdde736 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -55,7 +55,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.72 2008/02/20 14:01:45 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.73 2008/03/14 17:25:58 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -285,6 +285,7 @@ static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm, static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze, int freeze_min_age, + bool for_wraparound, BufferAccessStrategy bstrategy); static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid); static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared, @@ -2095,14 +2096,6 @@ do_autovacuum(void) /* clean up memory before each iteration */ MemoryContextResetAndDeleteChildren(PortalContext); - /* set the "vacuum for wraparound" flag in PGPROC */ - if (tab->at_wraparound) - { - LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); - MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND; - LWLockRelease(ProcArrayLock); - } - /* * Save the relation name for a possible error message, to avoid a * catalog lookup in case of an error. Note: they must live in a @@ -2126,6 +2119,7 @@ do_autovacuum(void) tab->at_dovacuum, tab->at_doanalyze, tab->at_freeze_min_age, + tab->at_wraparound, bstrategy); /* @@ -2604,7 +2598,7 @@ relation_needs_vacanalyze(Oid relid, */ static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze, - int freeze_min_age, + int freeze_min_age, bool for_wraparound, BufferAccessStrategy bstrategy) { VacuumStmt vacstmt; @@ -2631,7 +2625,7 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze, /* Let pgstat know what we're doing */ autovac_report_activity(&vacstmt, relid); - vacuum(&vacstmt, list_make1_oid(relid), bstrategy, true); + vacuum(&vacstmt, list_make1_oid(relid), bstrategy, for_wraparound, true); MemoryContextSwitchTo(old_cxt); } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 295178c797..fbd8f0d564 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.289 2008/01/01 19:45:52 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.290 2008/03/14 17:25:58 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -1032,7 +1032,7 @@ ProcessUtility(Node *parsetree, break; case T_VacuumStmt: - vacuum((VacuumStmt *) parsetree, NIL, NULL, isTopLevel); + vacuum((VacuumStmt *) parsetree, NIL, NULL, false, isTopLevel); break; case T_ExplainStmt: diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 1a3a4f6918..d5ebec0010 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.75 2008/01/01 19:45:57 momjian Exp $ + * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.76 2008/03/14 17:25:59 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -114,7 +114,7 @@ extern int vacuum_freeze_min_age; /* in commands/vacuum.c */ extern void vacuum(VacuumStmt *vacstmt, List *relids, - BufferAccessStrategy bstrategy, bool isTopLevel); + BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel); extern void vac_open_indexes(Relation relation, LOCKMODE lockmode, int *nindexes, Relation **Irel); extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode); -- 2.40.0