Force VACUUM to recalculate oldestXmin even when we haven't changed our
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 1 Sep 2009 04:46:49 +0000 (04:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 1 Sep 2009 04:46:49 +0000 (04:46 +0000)
own database's datfrozenxid, if the current value is old enough to be
forcing autovacuums or warning messages.  This ensures that a bogus
value is replaced as soon as possible.  Per a comment from Heikki.

src/backend/access/transam/varsup.c
src/backend/commands/vacuum.c
src/include/access/transam.h

index f4dc2df0481f0a818416dff339735186561f4190..f8e3f365a151ff95307b14d136370ff66bc531c8 100644 (file)
@@ -372,32 +372,41 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
 
 
 /*
- * TransactionIdLimitIsValid -- is the shared XID wrap-limit data sane?
+ * ForceTransactionIdLimitUpdate -- does the XID wrap-limit data need updating?
  *
  * We primarily check whether oldestXidDB is valid.  The cases we have in
  * mind are that that database was dropped, or the field was reset to zero
  * by pg_resetxlog.  In either case we should force recalculation of the
- * wrap limit.  In future we might add some more sanity checks here.
+ * wrap limit.  Also do it if oldestXid is old enough to be forcing
+ * autovacuums or other actions; this ensures we update our state as soon
+ * as possible once extra overhead is being incurred.
  */
 bool
-TransactionIdLimitIsValid(void)
+ForceTransactionIdLimitUpdate(void)
 {
+       TransactionId nextXid;
+       TransactionId xidVacLimit;
        TransactionId oldestXid;
        Oid                     oldestXidDB;
 
        /* Locking is probably not really necessary, but let's be careful */
        LWLockAcquire(XidGenLock, LW_SHARED);
+       nextXid = ShmemVariableCache->nextXid;
+       xidVacLimit = ShmemVariableCache->xidVacLimit;
        oldestXid = ShmemVariableCache->oldestXid;
        oldestXidDB = ShmemVariableCache->oldestXidDB;
        LWLockRelease(XidGenLock);
 
        if (!TransactionIdIsNormal(oldestXid))
-               return false;                   /* shouldn't happen, but just in case */
+               return true;                    /* shouldn't happen, but just in case */
+       if (TransactionIdFollowsOrEquals(nextXid, xidVacLimit) &&
+               TransactionIdIsValid(xidVacLimit))
+               return true;                    /* past VacLimit, don't delay updating */
        if (!SearchSysCacheExists(DATABASEOID,
                                                          ObjectIdGetDatum(oldestXidDB),
                                                          0, 0, 0))
-               return false;                   /* could happen, per comment above */
-       return true;
+               return true;                    /* could happen, per comments above */
+       return false;
 }
 
 
index 1349de2f728731ccb616899c6ac86f3eaf4a9613..c9c9baad54b664406ba710052e8e61e9acaacc10 100644 (file)
@@ -893,9 +893,10 @@ vac_update_datfrozenxid(void)
 
        /*
         * If we were able to advance datfrozenxid, see if we can truncate pg_clog.
-        * Also do it if the shared XID-wrap-limit info is stale.
+        * Also do it if the shared XID-wrap-limit info is stale, since this
+        * action will update that too.
         */
-       if (dirty || !TransactionIdLimitIsValid())
+       if (dirty || ForceTransactionIdLimitUpdate())
                vac_truncate_clog(newFrozenXid);
 }
 
index 9b19a754e7fbddf69ca8d70b492c2610a10b6adb..8ce30e3ec4985d36462202542b930eb38b3dd524 100644 (file)
@@ -156,7 +156,7 @@ extern TransactionId GetNewTransactionId(bool isSubXact);
 extern TransactionId ReadNewTransactionId(void);
 extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
                                          Oid oldest_datoid);
-extern bool TransactionIdLimitIsValid(void);
+extern bool ForceTransactionIdLimitUpdate(void);
 extern Oid     GetNewObjectId(void);
 
 #endif   /* TRAMSAM_H */