summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2008-03-14 17:26:01 +0000
committerAlvaro Herrera2008-03-14 17:26:01 +0000
commit82a3a41395876c65a24e0c7750794b9fd07c5d86 (patch)
tree23f112b7b75173c361b8fef538ade2cb76452b58
parent47870ef1927a089c4603f5fce15a811cc703787a (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 [email protected], though I didn't use his patch.
-rw-r--r--src/backend/commands/vacuum.c21
-rw-r--r--src/backend/postmaster/autovacuum.c14
-rw-r--r--src/backend/tcop/utility.c2
-rw-r--r--src/include/commands/vacuum.h2
4 files changed, 22 insertions, 17 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 4a38aefb65..abd09a6499 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -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 9c2ba03c04..79baefd6ab 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -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 9949e73700..c49574cd34 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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 589a6d23bd..974f86ca2e 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -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);