From 9c54cfb4937f49301793f1ec39dd8526baa8139d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 2 Apr 2002 05:11:55 +0000 Subject: [PATCH] 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. --- src/backend/commands/vacuum.c | 58 +++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index fff0320eca..ed3effab65 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); + } } -- 2.40.0