OSDN Git Service

Fix vacuum so that autovacuum is really not cancelled when doing an emergency
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 14 Mar 2008 17:25:59 +0000 (17:25 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 14 Mar 2008 17:25:59 +0000 (17:25 +0000)
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.

src/backend/commands/vacuum.c
src/backend/postmaster/autovacuum.c
src/backend/tcop/utility.c
src/include/commands/vacuum.h

index a073a1d..72a5069 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * 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;
 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.
index 9175f65..ca0bdde 100644 (file)
@@ -55,7 +55,7 @@
  *
  *
  * 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,
 
 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);
 }
 
index 295178c..fbd8f0d 100644 (file)
@@ -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.290 2008/03/14 17:25:58 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:
index 1a3a4f6..d5ebec0 100644 (file)
@@ -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.76 2008/03/14 17:25:59 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);