Skip to content

Commit 92685c3

Browse files
committed
Close race condition between datfrozen and relfrozen updates.
vac_update_datfrozenxid() did multiple loads of relfrozenxid and relminmxid from buffer memory, and it assumed each would get the same value. Not so if a concurrent vac_update_relstats() did an inplace update. Commit 2d2e40e fixed the same kind of bug in vac_truncate_clog(). Today's bug could cause the rel-level field and XIDs in the rel's rows to precede the db-level field. A cluster having such values should VACUUM affected tables. Back-patch to v12 (all supported versions). Discussion: https://postgr.es/m/20240423003956.e7.nmisch@google.com
1 parent b19255c commit 92685c3

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

src/backend/commands/vacuum.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,8 @@ vac_update_datfrozenxid(void)
16331633
/*
16341634
* We must seqscan pg_class to find the minimum Xid, because there is no
16351635
* index that can help us here.
1636+
*
1637+
* See vac_truncate_clog() for the race condition to prevent.
16361638
*/
16371639
relation = table_open(RelationRelationId, AccessShareLock);
16381640

@@ -1641,7 +1643,9 @@ vac_update_datfrozenxid(void)
16411643

16421644
while ((classTup = systable_getnext(scan)) != NULL)
16431645
{
1644-
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(classTup);
1646+
volatile FormData_pg_class *classForm = (Form_pg_class) GETSTRUCT(classTup);
1647+
TransactionId relfrozenxid = classForm->relfrozenxid;
1648+
TransactionId relminmxid = classForm->relminmxid;
16451649

16461650
/*
16471651
* Only consider relations able to hold unfrozen XIDs (anything else
@@ -1651,8 +1655,8 @@ vac_update_datfrozenxid(void)
16511655
classForm->relkind != RELKIND_MATVIEW &&
16521656
classForm->relkind != RELKIND_TOASTVALUE)
16531657
{
1654-
Assert(!TransactionIdIsValid(classForm->relfrozenxid));
1655-
Assert(!MultiXactIdIsValid(classForm->relminmxid));
1658+
Assert(!TransactionIdIsValid(relfrozenxid));
1659+
Assert(!MultiXactIdIsValid(relminmxid));
16561660
continue;
16571661
}
16581662

@@ -1671,34 +1675,34 @@ vac_update_datfrozenxid(void)
16711675
* before those relations have been scanned and cleaned up.
16721676
*/
16731677

1674-
if (TransactionIdIsValid(classForm->relfrozenxid))
1678+
if (TransactionIdIsValid(relfrozenxid))
16751679
{
1676-
Assert(TransactionIdIsNormal(classForm->relfrozenxid));
1680+
Assert(TransactionIdIsNormal(relfrozenxid));
16771681

16781682
/* check for values in the future */
1679-
if (TransactionIdPrecedes(lastSaneFrozenXid, classForm->relfrozenxid))
1683+
if (TransactionIdPrecedes(lastSaneFrozenXid, relfrozenxid))
16801684
{
16811685
bogus = true;
16821686
break;
16831687
}
16841688

16851689
/* determine new horizon */
1686-
if (TransactionIdPrecedes(classForm->relfrozenxid, newFrozenXid))
1687-
newFrozenXid = classForm->relfrozenxid;
1690+
if (TransactionIdPrecedes(relfrozenxid, newFrozenXid))
1691+
newFrozenXid = relfrozenxid;
16881692
}
16891693

1690-
if (MultiXactIdIsValid(classForm->relminmxid))
1694+
if (MultiXactIdIsValid(relminmxid))
16911695
{
16921696
/* check for values in the future */
1693-
if (MultiXactIdPrecedes(lastSaneMinMulti, classForm->relminmxid))
1697+
if (MultiXactIdPrecedes(lastSaneMinMulti, relminmxid))
16941698
{
16951699
bogus = true;
16961700
break;
16971701
}
16981702

16991703
/* determine new horizon */
1700-
if (MultiXactIdPrecedes(classForm->relminmxid, newMinMulti))
1701-
newMinMulti = classForm->relminmxid;
1704+
if (MultiXactIdPrecedes(relminmxid, newMinMulti))
1705+
newMinMulti = relminmxid;
17021706
}
17031707
}
17041708

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy