Commit adc4e1e6 authored by Alvaro Herrera's avatar Alvaro Herrera

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.
parent be5d6df3
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * 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; ...@@ -209,7 +209,8 @@ static BufferAccessStrategy vac_strategy;
static List *get_rel_oids(List *relids, const RangeVar *vacrel, static List *get_rel_oids(List *relids, const RangeVar *vacrel,
const char *stmttype); const char *stmttype);
static void vac_truncate_clog(TransactionId frozenXID); 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 full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel, static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages); VacPageList vacuum_pages, VacPageList fraged_pages);
...@@ -263,6 +264,9 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page); ...@@ -263,6 +264,9 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page);
* relation OIDs to be processed, and vacstmt->relation is ignored. * relation OIDs to be processed, and vacstmt->relation is ignored.
* (The non-NIL case is currently only used by autovacuum.) * (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 * 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. * in to use the same buffer strategy object across multiple vacuum() calls.
* *
...@@ -274,7 +278,7 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page); ...@@ -274,7 +278,7 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page);
*/ */
void void
vacuum(VacuumStmt *vacstmt, List *relids, vacuum(VacuumStmt *vacstmt, List *relids,
BufferAccessStrategy bstrategy, bool isTopLevel) BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{ {
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
volatile MemoryContext anl_context = NULL; volatile MemoryContext anl_context = NULL;
...@@ -421,7 +425,7 @@ vacuum(VacuumStmt *vacstmt, List *relids, ...@@ -421,7 +425,7 @@ vacuum(VacuumStmt *vacstmt, List *relids,
Oid relid = lfirst_oid(cur); Oid relid = lfirst_oid(cur);
if (vacstmt->vacuum) if (vacstmt->vacuum)
vacuum_rel(relid, vacstmt, RELKIND_RELATION); vacuum_rel(relid, vacstmt, RELKIND_RELATION, for_wraparound);
if (vacstmt->analyze) if (vacstmt->analyze)
{ {
...@@ -966,7 +970,8 @@ vac_truncate_clog(TransactionId frozenXID) ...@@ -966,7 +970,8 @@ vac_truncate_clog(TransactionId frozenXID)
* At entry and exit, we are not inside a transaction. * At entry and exit, we are not inside a transaction.
*/ */
static void 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; LOCKMODE lmode;
Relation onerel; Relation onerel;
...@@ -999,6 +1004,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -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 * contents of other tables is arguably broken, but we won't break it
* here by violating transaction semantics.) * 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 * Note: this flag remains set until CommitTransaction or
* AbortTransaction. We don't want to clear it until we reset * AbortTransaction. We don't want to clear it until we reset
* MyProc->xid/xmin, else OldestXmin might appear to go backwards, * MyProc->xid/xmin, else OldestXmin might appear to go backwards,
...@@ -1006,6 +1015,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -1006,6 +1015,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
*/ */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyProc->vacuumFlags |= PROC_IN_VACUUM; MyProc->vacuumFlags |= PROC_IN_VACUUM;
if (for_wraparound)
MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
LWLockRelease(ProcArrayLock); LWLockRelease(ProcArrayLock);
} }
...@@ -1147,7 +1158,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -1147,7 +1158,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
* totally unimportant for toast relations. * totally unimportant for toast relations.
*/ */
if (toast_relid != InvalidOid) 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. * Now release the session-level lock on the master table.
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -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, static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum,
bool doanalyze, int freeze_min_age, bool doanalyze, int freeze_min_age,
bool for_wraparound,
BufferAccessStrategy bstrategy); BufferAccessStrategy bstrategy);
static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid); static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid);
static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared, static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
...@@ -2095,14 +2096,6 @@ do_autovacuum(void) ...@@ -2095,14 +2096,6 @@ do_autovacuum(void)
/* clean up memory before each iteration */ /* clean up memory before each iteration */
MemoryContextResetAndDeleteChildren(PortalContext); 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 * 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 * catalog lookup in case of an error. Note: they must live in a
...@@ -2126,6 +2119,7 @@ do_autovacuum(void) ...@@ -2126,6 +2119,7 @@ do_autovacuum(void)
tab->at_dovacuum, tab->at_dovacuum,
tab->at_doanalyze, tab->at_doanalyze,
tab->at_freeze_min_age, tab->at_freeze_min_age,
tab->at_wraparound,
bstrategy); bstrategy);
/* /*
...@@ -2604,7 +2598,7 @@ relation_needs_vacanalyze(Oid relid, ...@@ -2604,7 +2598,7 @@ relation_needs_vacanalyze(Oid relid,
*/ */
static void static void
autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze, autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
int freeze_min_age, int freeze_min_age, bool for_wraparound,
BufferAccessStrategy bstrategy) BufferAccessStrategy bstrategy)
{ {
VacuumStmt vacstmt; VacuumStmt vacstmt;
...@@ -2631,7 +2625,7 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze, ...@@ -2631,7 +2625,7 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
/* Let pgstat know what we're doing */ /* Let pgstat know what we're doing */
autovac_report_activity(&vacstmt, relid); 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); MemoryContextSwitchTo(old_cxt);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -1032,7 +1032,7 @@ ProcessUtility(Node *parsetree,
break; break;
case T_VacuumStmt: case T_VacuumStmt:
vacuum((VacuumStmt *) parsetree, NIL, NULL, isTopLevel); vacuum((VacuumStmt *) parsetree, NIL, NULL, false, isTopLevel);
break; break;
case T_ExplainStmt: case T_ExplainStmt:
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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; ...@@ -114,7 +114,7 @@ extern int vacuum_freeze_min_age;
/* in commands/vacuum.c */ /* in commands/vacuum.c */
extern void vacuum(VacuumStmt *vacstmt, List *relids, 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, extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
int *nindexes, Relation **Irel); int *nindexes, Relation **Irel);
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode); extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment