mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-01 19:45:33 +08:00
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.
This commit is contained in:
parent
c666edb5eb
commit
9c37a4810e
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user