@@ -1066,6 +1066,12 @@ vac_truncate_clog(TransactionId frozenXID,
10661066/*
10671067 * Scan pg_database to compute the minimum datfrozenxid/datminmxid
10681068 *
1069+ * Since vac_update_datfrozenxid updates datfrozenxid/datminmxid in-place,
1070+ * the values could change while we look at them. Fetch each one just
1071+ * once to ensure sane behavior of the comparison logic. (Here, as in
1072+ * many other places, we assume that fetching or updating an XID in shared
1073+ * storage is atomic.)
1074+ *
10691075 * Note: we need not worry about a race condition with new entries being
10701076 * inserted by CREATE DATABASE. Any such entry will have a copy of some
10711077 * existing DB's datfrozenxid, and that source DB cannot be ours because
@@ -1081,10 +1087,12 @@ vac_truncate_clog(TransactionId frozenXID,
10811087
10821088while ((tuple = heap_getnext (scan ,ForwardScanDirection ))!= NULL )
10831089{
1084- Form_pg_database dbform = (Form_pg_database )GETSTRUCT (tuple );
1090+ volatile FormData_pg_database * dbform = (Form_pg_database )GETSTRUCT (tuple );
1091+ TransactionId datfrozenxid = dbform -> datfrozenxid ;
1092+ TransactionId datminmxid = dbform -> datminmxid ;
10851093
1086- Assert (TransactionIdIsNormal (dbform -> datfrozenxid ));
1087- Assert (MultiXactIdIsValid (dbform -> datminmxid ));
1094+ Assert (TransactionIdIsNormal (datfrozenxid ));
1095+ Assert (MultiXactIdIsValid (datminmxid ));
10881096
10891097/*
10901098 * If things are working properly, no database should have a
@@ -1095,21 +1103,21 @@ vac_truncate_clog(TransactionId frozenXID,
10951103 * databases have been scanned and cleaned up. (We will issue the
10961104 * "already wrapped" warning if appropriate, though.)
10971105 */
1098- if (TransactionIdPrecedes (lastSaneFrozenXid ,dbform -> datfrozenxid )||
1099- MultiXactIdPrecedes (lastSaneMinMulti ,dbform -> datminmxid ))
1106+ if (TransactionIdPrecedes (lastSaneFrozenXid ,datfrozenxid )||
1107+ MultiXactIdPrecedes (lastSaneMinMulti ,datminmxid ))
11001108bogus = true;
11011109
1102- if (TransactionIdPrecedes (nextXID ,dbform -> datfrozenxid ))
1110+ if (TransactionIdPrecedes (nextXID ,datfrozenxid ))
11031111frozenAlreadyWrapped = true;
1104- else if (TransactionIdPrecedes (dbform -> datfrozenxid ,frozenXID ))
1112+ else if (TransactionIdPrecedes (datfrozenxid ,frozenXID ))
11051113{
1106- frozenXID = dbform -> datfrozenxid ;
1114+ frozenXID = datfrozenxid ;
11071115oldestxid_datoid = HeapTupleGetOid (tuple );
11081116}
11091117
1110- if (MultiXactIdPrecedes (dbform -> datminmxid ,minMulti ))
1118+ if (MultiXactIdPrecedes (datminmxid ,minMulti ))
11111119{
1112- minMulti = dbform -> datminmxid ;
1120+ minMulti = datminmxid ;
11131121minmulti_datoid = HeapTupleGetOid (tuple );
11141122}
11151123}