Skip to content

Commit 9c37a48

Browse files
committed
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.
1 parent c666edb commit 9c37a48

File tree

4 files changed

+26
-21
lines changed

4 files changed

+26
-21
lines changed

src/backend/commands/vacuum.c

Lines changed: 17 additions & 6 deletions
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.364 2008/02/11 19:14:30 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.364.2.1 2008/03/14 17:26:00 alvherre Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -208,7 +208,8 @@ static BufferAccessStrategy vac_strategy;
208208
static List *get_rel_oids(List *relids, const RangeVar *vacrel,
209209
const char *stmttype);
210210
static void vac_truncate_clog(TransactionId frozenXID);
211-
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind);
211+
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind,
212+
bool for_wraparound);
212213
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
213214
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
214215
VacPageList vacuum_pages, VacPageList fraged_pages);
@@ -262,6 +263,9 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page);
262263
* relation OIDs to be processed, and vacstmt->relation is ignored.
263264
* (The non-NIL case is currently only used by autovacuum.)
264265
*
266+
* for_wraparound is used by autovacuum to let us know when it's forcing
267+
* a vacuum for wraparound, which should not be auto-cancelled.
268+
*
265269
* bstrategy is normally given as NULL, but in autovacuum it can be passed
266270
* in to use the same buffer strategy object across multiple vacuum() calls.
267271
*
@@ -273,7 +277,7 @@ static Size PageGetFreeSpaceWithFillFactor(Relation relation, Page page);
273277
*/
274278
void
275279
vacuum(VacuumStmt *vacstmt, List *relids,
276-
BufferAccessStrategy bstrategy, bool isTopLevel)
280+
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
277281
{
278282
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
279283
volatile MemoryContext anl_context = NULL;
@@ -420,7 +424,7 @@ vacuum(VacuumStmt *vacstmt, List *relids,
420424
Oid relid = lfirst_oid(cur);
421425

422426
if (vacstmt->vacuum)
423-
vacuum_rel(relid, vacstmt, RELKIND_RELATION);
427+
vacuum_rel(relid, vacstmt, RELKIND_RELATION, for_wraparound);
424428

425429
if (vacstmt->analyze)
426430
{
@@ -965,7 +969,8 @@ vac_truncate_clog(TransactionId frozenXID)
965969
* At entry and exit, we are not inside a transaction.
966970
*/
967971
static void
968-
vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
972+
vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind,
973+
bool for_wraparound)
969974
{
970975
LOCKMODE lmode;
971976
Relation onerel;
@@ -998,13 +1003,19 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
9981003
* contents of other tables is arguably broken, but we won't break it
9991004
* here by violating transaction semantics.)
10001005
*
1006+
* We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down
1007+
* by autovacuum; it's used to avoid cancelling a vacuum that was
1008+
* invoked in an emergency.
1009+
*
10011010
* Note: this flag remains set until CommitTransaction or
10021011
* AbortTransaction. We don't want to clear it until we reset
10031012
* MyProc->xid/xmin, else OldestXmin might appear to go backwards,
10041013
* which is probably Not Good.
10051014
*/
10061015
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
10071016
MyProc->vacuumFlags |= PROC_IN_VACUUM;
1017+
if (for_wraparound)
1018+
MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
10081019
LWLockRelease(ProcArrayLock);
10091020
}
10101021

@@ -1137,7 +1148,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
11371148
* totally unimportant for toast relations.
11381149
*/
11391150
if (toast_relid != InvalidOid)
1140-
vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE);
1151+
vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE, for_wraparound);
11411152

11421153
/*
11431154
* Now release the session-level lock on the master table.

src/backend/postmaster/autovacuum.c

Lines changed: 5 additions & 11 deletions
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.71.2.1 2008/02/20 16:48:12 alvherre Exp $
58+
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.71.2.2 2008/03/14 17:26:01 alvherre Exp $
5959
*
6060
*-------------------------------------------------------------------------
6161
*/
@@ -285,6 +285,7 @@ static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
285285

286286
static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum,
287287
bool doanalyze, int freeze_min_age,
288+
bool for_wraparound,
288289
BufferAccessStrategy bstrategy);
289290
static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid);
290291
static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
@@ -2095,14 +2096,6 @@ do_autovacuum(void)
20952096
/* clean up memory before each iteration */
20962097
MemoryContextResetAndDeleteChildren(PortalContext);
20972098

2098-
/* set the "vacuum for wraparound" flag in PGPROC */
2099-
if (tab->at_wraparound)
2100-
{
2101-
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
2102-
MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
2103-
LWLockRelease(ProcArrayLock);
2104-
}
2105-
21062099
/*
21072100
* Save the relation name for a possible error message, to avoid a
21082101
* catalog lookup in case of an error. Note: they must live in a
@@ -2126,6 +2119,7 @@ do_autovacuum(void)
21262119
tab->at_dovacuum,
21272120
tab->at_doanalyze,
21282121
tab->at_freeze_min_age,
2122+
tab->at_wraparound,
21292123
bstrategy);
21302124

21312125
/*
@@ -2604,7 +2598,7 @@ relation_needs_vacanalyze(Oid relid,
26042598
*/
26052599
static void
26062600
autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
2607-
int freeze_min_age,
2601+
int freeze_min_age, bool for_wraparound,
26082602
BufferAccessStrategy bstrategy)
26092603
{
26102604
VacuumStmt vacstmt;
@@ -2631,7 +2625,7 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
26312625
/* Let pgstat know what we're doing */
26322626
autovac_report_activity(&vacstmt, relid);
26332627

2634-
vacuum(&vacstmt, list_make1_oid(relid), bstrategy, true);
2628+
vacuum(&vacstmt, list_make1_oid(relid), bstrategy, for_wraparound, true);
26352629
MemoryContextSwitchTo(old_cxt);
26362630
}
26372631

src/backend/tcop/utility.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.289 2008/01/01 19:45:52 momjian Exp $
13+
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.289.2.1 2008/03/14 17:26:01 alvherre Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -1032,7 +1032,7 @@ ProcessUtility(Node *parsetree,
10321032
break;
10331033

10341034
case T_VacuumStmt:
1035-
vacuum((VacuumStmt *) parsetree, NIL, NULL, isTopLevel);
1035+
vacuum((VacuumStmt *) parsetree, NIL, NULL, false, isTopLevel);
10361036
break;
10371037

10381038
case T_ExplainStmt:

src/include/commands/vacuum.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.75 2008/01/01 19:45:57 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.75.2.1 2008/03/14 17:26:01 alvherre Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -114,7 +114,7 @@ extern int vacuum_freeze_min_age;
114114

115115
/* in commands/vacuum.c */
116116
extern void vacuum(VacuumStmt *vacstmt, List *relids,
117-
BufferAccessStrategy bstrategy, bool isTopLevel);
117+
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel);
118118
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
119119
int *nindexes, Relation **Irel);
120120
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);

0 commit comments

Comments
 (0)