8000 Fetch XIDs atomically during vac_truncate_clog(). · rtpg/postgres@5551dac · GitHub
[go: up one dir, main page]

Skip to content

Commit 5551dac

Browse files
committed
Fetch XIDs atomically during vac_truncate_clog().
Because vac_update_datfrozenxid() updates datfrozenxid and datminmxid in-place, it's unsafe to assume that successive reads of those values will give consistent results. Fetch each one just once to ensure sane behavior in the minimum calculation. Noted while reviewing Alexander Korotkov's patch in the same area. Discussion: <8564.1464116473@sss.pgh.pa.us>
1 parent fe1731f commit 5551dac

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

src/backend/commands/vacuum.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,12 @@ vac_truncate_clog(TransactionId frozenXID)
797797
/*
798798
* Scan pg_database to compute the minimum datfrozenxid
799799
*
800+
* Since vac_update_datfrozenxid updates datfrozenxid in-place,
801+
* the values could change while we look at them. Fetch each one just
802+
* once to ensure sane behavior of the comparison logic. (Here, as in
803+
* many other places, we assume that fetching or updating an XID in shared
804+
* storage is atomic.)
805+
*
800806
* Note: we need not worry about a race condition with new entries being
801807
* inserted by CREATE DATABASE. Any such entry will have a copy of some
802808
* existing DB's datfrozenxid, and that source DB cannot be ours because
@@ -812,15 +818,16 @@ vac_truncate_clog(TransactionId frozenXID)
812818

813819
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
814820
{
815-
Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
821+
volatile FormData_pg_database *dbform = (Form_pg_database) GETSTRUCT(tuple);
822+
TransactionId datfrozenxid = dbform->datfrozenxid;
816823

817-
Assert(TransactionIdIsNormal(dbform->datfrozenxid));
824+
Assert(TransactionIdIsNormal(datfrozenxid));
818825

819-
if (TransactionIdPrecedes(nextXID, dbform->datfrozenxid))
826+
if (TransactionIdPrecedes(nextXID, datfrozenxid))
820827
frozenAlreadyWrapped = true;
821-
else if (TransactionIdPrecedes(dbform->datfrozenxid, frozenXID))
828+
else if (TransactionIdPrecedes(datfrozenxid, frozenXID))
822829
{
823-
frozenXID = dbform->datfrozenxid;
830+
frozenXID = datfrozenxid;
824831
oldest_datoid = HeapTupleGetOid(tuple);
825832
}
826833
}

0 commit comments

Comments
 (0)
0