@@ -1067,6 +1067,12 @@ vac_truncate_clog(TransactionId frozenXID,
1067
1067
/*
1068
1068
* Scan pg_database to compute the minimum datfrozenxid/datminmxid
1069
1069
*
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
+ *
1070
1076
* Note: we need not worry about a race condition with new entries being
1071
1077
* inserted by CREATE DATABASE. Any such entry will have a copy of some
1072
1078
* existing DB's datfrozenxid, and that source DB cannot be ours because
@@ -1082,10 +1088,12 @@ vac_truncate_clog(TransactionId frozenXID,
1082
1088
1083
1089
while ((tuple = heap_getnext (scan , ForwardScanDirection )) != NULL )
1084
1090
{
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 ;
1086
1094
1087
- Assert (TransactionIdIsNormal (dbform -> datfrozenxid ));
1088
- Assert (MultiXactIdIsValid (dbform -> datminmxid ));
1095
+ Assert (TransactionIdIsNormal (datfrozenxid ));
1096
+ Assert (MultiXactIdIsValid (datminmxid ));
1089
1097
1090
1098
/*
1091
1099
* If things are working properly, no database should have a
@@ -1096,21 +1104,21 @@ vac_truncate_clog(TransactionId frozenXID,
1096
1104
* databases have been scanned and cleaned up. (We will issue the
1097
1105
* "already wrapped" warning if appropriate, though.)
1098
1106
*/
1099
- if (TransactionIdPrecedes (lastSaneFrozenXid , dbform -> datfrozenxid ) ||
1100
- MultiXactIdPrecedes (lastSaneMinMulti , dbform -> datminmxid ))
1107
+ if (TransactionIdPrecedes (lastSaneFrozenXid , datfrozenxid ) ||
1108
+ MultiXactIdPrecedes (lastSaneMinMulti , datminmxid ))
1101
1109
bogus = true;
1102
1110
1103
- if (TransactionIdPrecedes (nextXID , dbform -> datfrozenxid ))
1111
+ if (TransactionIdPrecedes (nextXID , datfrozenxid ))
1104
1112
frozenAlreadyWrapped = true;
1105
- else if (TransactionIdPrecedes (dbform -> datfrozenxid , frozenXID ))
1113
+ else if (TransactionIdPrecedes (datfrozenxid , frozenXID ))
1106
1114
{
1107
- frozenXID = dbform -> datfrozenxid ;
1115
+ frozenXID = datfrozenxid ;
1108
1116
oldestxid_datoid = HeapTupleGetOid (tuple );
1109
1117
}
1110
1118
1111
- if (MultiXactIdPrecedes (dbform -> datminmxid , minMulti ))
1119
+ if (MultiXactIdPrecedes (datminmxid , minMulti ))
1112
1120
{
1113
- minMulti = dbform -> datminmxid ;
1121
+ minMulti = datminmxid ;
1114
1122
minmulti_datoid = HeapTupleGetOid (tuple );
1115
1123
}
1116
1124
}
0 commit comments