aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-04-02 05:11:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-04-02 05:11:55 +0000
commit9c54cfb4937f49301793f1ec39dd8526baa8139d (patch)
tree68b1088e17d45f92468ad29e25dbff8aa5e4cf2d
parent688781d4507ea4fbe1a5e6ba1daaa85468ef82b9 (diff)
downloadpostgresql-9c54cfb4937f49301793f1ec39dd8526baa8139d.tar.gz
postgresql-9c54cfb4937f49301793f1ec39dd8526baa8139d.zip
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 fff0320eca2..ed3effab651 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.221 2002/04/02 01:03:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.222 2002/04/02 05:11:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -557,10 +557,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);
@@ -575,28 +580,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(WARNING, "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(WARNING, "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(WARNING, "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(WARNING, "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);
+ }
}