summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2008-03-14 17:26:01 +0000
committerAlvaro Herrera2008-03-14 17:26:01 +0000
commit9c37a4810eee90da9d009dbf31f41ecebcc643f5 (patch)
tree1fd6f660348b3e92d6de9e9903da19a618f26510
parentc666edb5eb8c9f96788f9cf5fbd74f7727ba46d7 (diff)
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.
-rw-r--r--src/backend/commands/vacuum.c23
-rw-r--r--src/backend/postmaster/autovacuum.c16
-rw-r--r--src/backend/tcop/utility.c4
-rw-r--r--src/include/commands/vacuum.h4
4 files changed, 26 insertions, 21 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 20374f4cd65..1a0eecd9490 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.364 2008/02/11 19:14:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.364.2.1 2008/03/14 17:26:00 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -208,7 +208,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);
@@ -262,6 +263,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.
*
@@ -273,7 +277,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;
@@ -420,7 +424,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)
{
@@ -965,7 +969,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;
@@ -998,6 +1003,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,
@@ -1005,6 +1014,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);
}
@@ -1137,7 +1148,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 cc0cd0478d4..7d861c1d21f 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.71.2.1 2008/02/20 16:48:12 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.71.2.2 2008/03/14 17:26:01 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 295178c7974..db17519ab88 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.289.2.1 2008/03/14 17:26:01 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 1a3a4f69182..4beb1f8c785 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.75.2.1 2008/03/14 17:26:01 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);