summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-04-02 05:12:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-04-02 05:12:00 +0000
commitaf997458ebe32f1f9a10492bbe3aef549ada4806 (patch)
tree9b527867f0bde70ac7410ab48c98e40d95703767
parent9de8b7b9f21ecda7bbf469db987221ff6b6e53cc (diff)
Fix CLOG truncation code to not do the Wrong Thing when there are already
wrapped-around databases. The unvacuumed databases might be fine, or they might not, but things will definitely not be fine if we remove the wrong CLOG segments. Per trouble report from Gary Wolfe, 1-Apr-2002.
-rw-r--r--src/backend/commands/vacuum.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 894a7e32855..a853344b9e4 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.213 2002/01/06 00:37:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.213.2.1 2002/04/02 05:12:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -616,10 +616,15 @@ vac_update_dbstats(Oid dbid,
static void
vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
{
+ TransactionId myXID;
Relation relation;
HeapScanDesc scan;
HeapTuple tuple;
int32 age;
+ bool vacuumAlreadyWrapped = false;
+ bool frozenAlreadyWrapped = false;
+
+ myXID = GetCurrentTransactionId();
relation = heap_openr(DatabaseRelationName, AccessShareLock);
@@ -634,28 +639,55 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
if (!dbform->datallowconn)
continue;
- if (TransactionIdIsNormal(dbform->datvacuumxid) &&
- TransactionIdPrecedes(dbform->datvacuumxid, vacuumXID))
- vacuumXID = dbform->datvacuumxid;
- if (TransactionIdIsNormal(dbform->datfrozenxid) &&
- TransactionIdPrecedes(dbform->datfrozenxid, frozenXID))
- frozenXID = dbform->datfrozenxid;
+ if (TransactionIdIsNormal(dbform->datvacuumxid))
+ {
+ if (TransactionIdPrecedes(myXID, dbform->datvacuumxid))
+ vacuumAlreadyWrapped = true;
+ else if (TransactionIdPrecedes(dbform->datvacuumxid, vacuumXID))
+ vacuumXID = dbform->datvacuumxid;
+ }
+ if (TransactionIdIsNormal(dbform->datfrozenxid))
+ {
+ if (TransactionIdPrecedes(myXID, dbform->datfrozenxid))
+ frozenAlreadyWrapped = true;
+ else if (TransactionIdPrecedes(dbform->datfrozenxid, frozenXID))
+ frozenXID = dbform->datfrozenxid;
+ }
}
heap_endscan(scan);
heap_close(relation, AccessShareLock);
+ /*
+ * Do not truncate CLOG if we seem to have suffered wraparound already;
+ * the computed minimum XID might be bogus.
+ */
+ if (vacuumAlreadyWrapped)
+ {
+ elog(NOTICE, "Some databases have not been vacuumed in over 2 billion transactions."
+ "\n\tYou may have already suffered transaction-wraparound data loss.");
+ return;
+ }
+
/* Truncate CLOG to the oldest vacuumxid */
TruncateCLOG(vacuumXID);
/* Give warning about impending wraparound problems */
- age = (int32) (GetCurrentTransactionId() - frozenXID);
- if (age > (int32) ((MaxTransactionId >> 3) * 3))
- elog(NOTICE, "Some databases have not been vacuumed in %d transactions."
- "\n\tBetter vacuum them within %d transactions,"
- "\n\tor you may have a wraparound failure.",
- age, (int32) (MaxTransactionId >> 1) - age);
+ if (frozenAlreadyWrapped)
+ {
+ elog(NOTICE, "Some databases have not been vacuumed in over 1 billion transactions."
+ "\n\tBetter vacuum them soon, or you may have a wraparound failure.");
+ }
+ else
+ {
+ age = (int32) (myXID - frozenXID);
+ if (age > (int32) ((MaxTransactionId >> 3) * 3))
+ elog(NOTICE, "Some databases have not been vacuumed in %d transactions."
+ "\n\tBetter vacuum them within %d transactions,"
+ "\n\tor you may have a wraparound failure.",
+ age, (int32) (MaxTransactionId >> 1) - age);
+ }
}