Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e83ebfe

Browse files
Have VACUUM warn on relfrozenxid "in the future".
Commits 74cf7d4 and a61daa1 fixed pg_upgrade bugs involving oversights in how relfrozenxid or relminmxid are carried forward or initialized. Corruption caused by bugs of this nature was ameliorated by commit 78db307, which taught VACUUM to always overwrite existing invalid relfrozenxid or relminmxid values that are apparently "in the future". Extend that work now by showing a warning in the event of overwriting either relfrozenxid or relminmxid due to an existing value that is "in the future". There is probably a decent chance that the sanity checks added by commit 699bf7d will raise an error before VACUUM reaches this point, but we shouldn't rely on that. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CAH2-WzmRZEzeGvLv8yDW0AbFmSvJjTziORqjVUrf74mL4GL0Ww@mail.gmail.com
1 parent 1691512 commit e83ebfe

File tree

1 file changed

+52
-18
lines changed

1 file changed

+52
-18
lines changed

src/backend/commands/vacuum.c

+52-18
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,11 @@ vac_update_relstats(Relation relation,
13401340
Relation rd;
13411341
HeapTuple ctup;
13421342
Form_pg_class pgcform;
1343-
bool dirty;
1343+
bool dirty,
1344+
futurexid,
1345+
futuremxid;
1346+
TransactionId oldfrozenxid;
1347+
MultiXactId oldminmulti;
13441348

13451349
rd = table_open(RelationRelationId, RowExclusiveLock);
13461350

@@ -1406,39 +1410,69 @@ vac_update_relstats(Relation relation,
14061410
* This should match vac_update_datfrozenxid() concerning what we consider
14071411
* to be "in the future".
14081412
*/
1413+
oldfrozenxid = pgcform->relfrozenxid;
1414+
futurexid = false;
14091415
if (frozenxid_updated)
14101416
*frozenxid_updated = false;
1411-
if (TransactionIdIsNormal(frozenxid) &&
1412-
pgcform->relfrozenxid != frozenxid &&
1413-
(TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid) ||
1414-
TransactionIdPrecedes(ReadNextTransactionId(),
1415-
pgcform->relfrozenxid)))
1417+
if (TransactionIdIsNormal(frozenxid) && oldfrozenxid != frozenxid)
14161418
{
1417-
if (frozenxid_updated)
1418-
*frozenxid_updated = true;
1419-
pgcform->relfrozenxid = frozenxid;
1420-
dirty = true;
1419+
bool update = false;
1420+
1421+
if (TransactionIdPrecedes(oldfrozenxid, frozenxid))
1422+
update = true;
1423+
else if (TransactionIdPrecedes(ReadNextTransactionId(), oldfrozenxid))
1424+
futurexid = update = true;
1425+
1426+
if (update)
1427+
{
1428+
pgcform->relfrozenxid = frozenxid;
1429+
dirty = true;
1430+
if (frozenxid_updated)
1431+
*frozenxid_updated = true;
1432+
}
14211433
}
14221434

14231435
/* Similarly for relminmxid */
1436+
oldminmulti = pgcform->relminmxid;
1437+
futuremxid = false;
14241438
if (minmulti_updated)
14251439
*minmulti_updated = false;
1426-
if (MultiXactIdIsValid(minmulti) &&
1427-
pgcform->relminmxid != minmulti &&
1428-
(MultiXactIdPrecedes(pgcform->relminmxid, minmulti) ||
1429-
MultiXactIdPrecedes(ReadNextMultiXactId(), pgcform->relminmxid)))
1440+
if (MultiXactIdIsValid(minmulti) && oldminmulti != minmulti)
14301441
{
1431-
if (minmulti_updated)
1432-
*minmulti_updated = true;
1433-
pgcform->relminmxid = minmulti;
1434-
dirty = true;
1442+
bool update = false;
1443+
1444+
if (MultiXactIdPrecedes(oldminmulti, minmulti))
1445+
update = true;
1446+
else if (MultiXactIdPrecedes(ReadNextMultiXactId(), oldminmulti))
1447+
futuremxid = update = true;
1448+
1449+
if (update)
1450+
{
1451+
pgcform->relminmxid = minmulti;
1452+
dirty = true;
1453+
if (minmulti_updated)
1454+
*minmulti_updated = true;
1455+
}
14351456
}
14361457

14371458
/* If anything changed, write out the tuple. */
14381459
if (dirty)
14391460
heap_inplace_update(rd, ctup);
14401461

14411462
table_close(rd, RowExclusiveLock);
1463+
1464+
if (futurexid)
1465+
ereport(WARNING,
1466+
(errcode(ERRCODE_DATA_CORRUPTED),
1467+
errmsg_internal("overwrote invalid relfrozenxid value %u with new value %u for table \"%s\"",
1468+
oldfrozenxid, frozenxid,
1469+
RelationGetRelationName(relation))));
1470+
if (futuremxid)
1471+
ereport(WARNING,
1472+
(errcode(ERRCODE_DATA_CORRUPTED),
1473+
errmsg_internal("overwrote invalid relminmxid value %u with new value %u for table \"%s\"",
1474+
oldminmulti, minmulti,
1475+
RelationGetRelationName(relation))));
14421476
}
14431477

14441478

0 commit comments

Comments
 (0)