mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 08:21:16 +02:00
Have VACUUM warn on relfrozenxid "in the future".
Commits74cf7d46
anda61daa14
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 commit78db307bb2
, 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 commit699bf7d05c
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
This commit is contained in:
parent
1691512674
commit
e83ebfe6d7
@ -1340,7 +1340,11 @@ vac_update_relstats(Relation relation,
|
|||||||
Relation rd;
|
Relation rd;
|
||||||
HeapTuple ctup;
|
HeapTuple ctup;
|
||||||
Form_pg_class pgcform;
|
Form_pg_class pgcform;
|
||||||
bool dirty;
|
bool dirty,
|
||||||
|
futurexid,
|
||||||
|
futuremxid;
|
||||||
|
TransactionId oldfrozenxid;
|
||||||
|
MultiXactId oldminmulti;
|
||||||
|
|
||||||
rd = table_open(RelationRelationId, RowExclusiveLock);
|
rd = table_open(RelationRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -1406,32 +1410,49 @@ vac_update_relstats(Relation relation,
|
|||||||
* This should match vac_update_datfrozenxid() concerning what we consider
|
* This should match vac_update_datfrozenxid() concerning what we consider
|
||||||
* to be "in the future".
|
* to be "in the future".
|
||||||
*/
|
*/
|
||||||
|
oldfrozenxid = pgcform->relfrozenxid;
|
||||||
|
futurexid = false;
|
||||||
if (frozenxid_updated)
|
if (frozenxid_updated)
|
||||||
*frozenxid_updated = false;
|
*frozenxid_updated = false;
|
||||||
if (TransactionIdIsNormal(frozenxid) &&
|
if (TransactionIdIsNormal(frozenxid) && oldfrozenxid != frozenxid)
|
||||||
pgcform->relfrozenxid != frozenxid &&
|
{
|
||||||
(TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid) ||
|
bool update = false;
|
||||||
TransactionIdPrecedes(ReadNextTransactionId(),
|
|
||||||
pgcform->relfrozenxid)))
|
if (TransactionIdPrecedes(oldfrozenxid, frozenxid))
|
||||||
|
update = true;
|
||||||
|
else if (TransactionIdPrecedes(ReadNextTransactionId(), oldfrozenxid))
|
||||||
|
futurexid = update = true;
|
||||||
|
|
||||||
|
if (update)
|
||||||
{
|
{
|
||||||
if (frozenxid_updated)
|
|
||||||
*frozenxid_updated = true;
|
|
||||||
pgcform->relfrozenxid = frozenxid;
|
pgcform->relfrozenxid = frozenxid;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
if (frozenxid_updated)
|
||||||
|
*frozenxid_updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similarly for relminmxid */
|
/* Similarly for relminmxid */
|
||||||
|
oldminmulti = pgcform->relminmxid;
|
||||||
|
futuremxid = false;
|
||||||
if (minmulti_updated)
|
if (minmulti_updated)
|
||||||
*minmulti_updated = false;
|
*minmulti_updated = false;
|
||||||
if (MultiXactIdIsValid(minmulti) &&
|
if (MultiXactIdIsValid(minmulti) && oldminmulti != minmulti)
|
||||||
pgcform->relminmxid != minmulti &&
|
{
|
||||||
(MultiXactIdPrecedes(pgcform->relminmxid, minmulti) ||
|
bool update = false;
|
||||||
MultiXactIdPrecedes(ReadNextMultiXactId(), pgcform->relminmxid)))
|
|
||||||
|
if (MultiXactIdPrecedes(oldminmulti, minmulti))
|
||||||
|
update = true;
|
||||||
|
else if (MultiXactIdPrecedes(ReadNextMultiXactId(), oldminmulti))
|
||||||
|
futuremxid = update = true;
|
||||||
|
|
||||||
|
if (update)
|
||||||
{
|
{
|
||||||
if (minmulti_updated)
|
|
||||||
*minmulti_updated = true;
|
|
||||||
pgcform->relminmxid = minmulti;
|
pgcform->relminmxid = minmulti;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
if (minmulti_updated)
|
||||||
|
*minmulti_updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If anything changed, write out the tuple. */
|
/* If anything changed, write out the tuple. */
|
||||||
@ -1439,6 +1460,19 @@ vac_update_relstats(Relation relation,
|
|||||||
heap_inplace_update(rd, ctup);
|
heap_inplace_update(rd, ctup);
|
||||||
|
|
||||||
table_close(rd, RowExclusiveLock);
|
table_close(rd, RowExclusiveLock);
|
||||||
|
|
||||||
|
if (futurexid)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||||
|
errmsg_internal("overwrote invalid relfrozenxid value %u with new value %u for table \"%s\"",
|
||||||
|
oldfrozenxid, frozenxid,
|
||||||
|
RelationGetRelationName(relation))));
|
||||||
|
if (futuremxid)
|
||||||
|
ereport(WARNING,
|
||||||
|
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||||
|
errmsg_internal("overwrote invalid relminmxid value %u with new value %u for table \"%s\"",
|
||||||
|
oldminmulti, minmulti,
|
||||||
|
RelationGetRelationName(relation))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user