@@ -1067,6 +1067,12 @@ vac_truncate_clog(TransactionId frozenXID,
10671067/*
10681068 * Scan pg_database to compute the minimum datfrozenxid/datminmxid
10691069 *
1070+ * Since vac_update_datfrozenxid updates datfrozenxid/datminmxid in-place,
1071+ * the values could change while we look at them. Fetch each one just
1072+ * once to ensure sane behavior of the comparison logic. (Here, as in
1073+ * many other places, we assume that fetching or updating an XID in shared
1074+ * storage is atomic.)
1075+ *
10701076 * Note: we need not worry about a race condition with new entries being
10711077 * inserted by CREATE DATABASE. Any such entry will have a copy of some
10721078 * existing DB's datfrozenxid, and that source DB cannot be ours because
@@ -1082,10 +1088,12 @@ vac_truncate_clog(TransactionId frozenXID,
10821088
10831089while ((tuple = heap_getnext (scan ,ForwardScanDirection ))!= NULL )
10841090{
1085- Form_pg_database dbform = (Form_pg_database )GETSTRUCT (tuple );
1091+ volatile FormData_pg_database * dbform = (Form_pg_database )GETSTRUCT (tuple );
1092+ TransactionId datfrozenxid = dbform -> datfrozenxid ;
1093+ TransactionId datminmxid = dbform -> datminmxid ;
10861094
1087- Assert (TransactionIdIsNormal (dbform -> datfrozenxid ));
1088- Assert (MultiXactIdIsValid (dbform -> datminmxid ));
1095+ Assert (TransactionIdIsNormal (datfrozenxid ));
1096+ Assert (MultiXactIdIsValid (datminmxid ));
10891097
10901098/*
10911099 * If things are working properly, no database should have a
@@ -1096,21 +1104,21 @@ vac_truncate_clog(TransactionId frozenXID,
10961104 * databases have been scanned and cleaned up. (We will issue the
10971105 * "already wrapped" warning if appropriate, though.)
10981106 */
1099- if (TransactionIdPrecedes (lastSaneFrozenXid ,dbform -> datfrozenxid )||
1100- MultiXactIdPrecedes (lastSaneMinMulti ,dbform -> datminmxid ))
1107+ if (TransactionIdPrecedes (lastSaneFrozenXid ,datfrozenxid )||
1108+ MultiXactIdPrecedes (lastSaneMinMulti ,datminmxid ))
11011109bogus = true;
11021110
1103- if (TransactionIdPrecedes (nextXID ,dbform -> datfrozenxid ))
1111+ if (TransactionIdPrecedes (nextXID ,datfrozenxid ))
11041112frozenAlreadyWrapped = true;
1105- else if (TransactionIdPrecedes (dbform -> datfrozenxid ,frozenXID ))
1113+ else if (TransactionIdPrecedes (datfrozenxid ,frozenXID ))
11061114{
1107- frozenXID = dbform -> datfrozenxid ;
1115+ frozenXID = datfrozenxid ;
11081116oldestxid_datoid = HeapTupleGetOid (tuple );
11091117}
11101118
1111- if (MultiXactIdPrecedes (dbform -> datminmxid ,minMulti ))
1119+ if (MultiXactIdPrecedes (datminmxid ,minMulti ))
11121120{
1113- minMulti = dbform -> datminmxid ;
1121+ minMulti = datminmxid ;
11141122minmulti_datoid = HeapTupleGetOid (tuple );
11151123}
11161124}