@@ -203,22 +203,8 @@ typedef struct MultiXactStateData
203
203
MultiXactId oldestMultiXactId ;
204
204
Oid oldestMultiXactDB ;
205
205
206
- /*
207
- * Oldest multixact offset that is potentially referenced by a multixact
208
- * referenced by a relation. We don't always know this value, so there's
209
- * a flag here to indicate whether or not we currently do.
210
- */
211
- MultiXactOffset oldestOffset ;
212
- bool oldestOffsetKnown ;
213
-
214
206
/* support for anti-wraparound measures */
215
207
MultiXactId multiVacLimit ;
216
- MultiXactId multiWarnLimit ;
217
- MultiXactId multiStopLimit ;
218
- MultiXactId multiWrapLimit ;
219
-
220
- /* support for members anti-wraparound measures */
221
- MultiXactOffset offsetStopLimit ; /* known if oldestOffsetKnown */
222
208
223
209
/*
224
210
* Per-backend data starts here. We have two arrays stored in the area
@@ -707,9 +693,6 @@ ReadNextMultiXactId(void)
707
693
mxid = MultiXactState -> nextMXact ;
708
694
LWLockRelease (MultiXactGenLock );
709
695
710
- if (mxid < FirstMultiXactId )
711
- mxid = FirstMultiXactId ;
712
-
713
696
return mxid ;
714
697
}
715
698
@@ -933,6 +916,42 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
933
916
/* Assign the MXID */
934
917
result = MultiXactState -> nextMXact ;
935
918
919
+ /*----------
920
+ * Check to see if it's safe to assign another MultiXactId. This protects
921
+ * against catastrophic data loss due to multixact wraparound. The basic
922
+ * rules are:
923
+ *
924
+ * If we're past multiVacLimit or the safe threshold for member storage
925
+ * space, or we don't know what the safe threshold for member storage is,
926
+ * start trying to force autovacuum cycles.
927
+ *
928
+ * Note these are pretty much the same protections in GetNewTransactionId.
929
+ *----------
930
+ */
931
+ if (!MultiXactIdPrecedes (result , MultiXactState -> multiVacLimit ))
932
+ {
933
+ /*
934
+ * For safety's sake, we release MultiXactGenLock while sending
935
+ * signals, warnings, etc. This is not so much because we care about
936
+ * preserving concurrency in this situation, as to avoid any
937
+ * possibility of deadlock while doing get_database_name(). First,
938
+ * copy all the shared values we'll need in this path.
939
+ */
940
+ LWLockRelease (MultiXactGenLock );
941
+
942
+ /*
943
+ * To avoid swamping the postmaster with signals, we issue the autovac
944
+ * request only once per 64K multis generated. This still gives
945
+ * plenty of chances before we get into real trouble.
946
+ */
947
+ if (IsUnderPostmaster && (result % 65536 ) == 0 )
948
+ SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_LAUNCHER );
949
+
950
+ /* Re-acquire lock and start over */
951
+ LWLockAcquire (MultiXactGenLock , LW_EXCLUSIVE );
952
+ result = MultiXactState -> nextMXact ;
953
+ }
954
+
936
955
/* Make sure there is room for the MXID in the file. */
937
956
ExtendMultiXactOffset (result );
938
957
@@ -1016,7 +1035,6 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
1016
1035
int length ;
1017
1036
int truelength ;
1018
1037
int i ;
1019
- MultiXactId oldestMXact ;
1020
1038
MultiXactId nextMXact ;
1021
1039
MultiXactId tmpMXact ;
1022
1040
MultiXactOffset nextOffset ;
@@ -1069,7 +1087,6 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
1069
1087
*/
1070
1088
LWLockAcquire (MultiXactGenLock , LW_SHARED );
1071
1089
1072
- oldestMXact = MultiXactState -> oldestMultiXactId ;
1073
1090
nextMXact = MultiXactState -> nextMXact ;
1074
1091
nextOffset = MultiXactState -> nextOffset ;
1075
1092
@@ -1974,50 +1991,9 @@ void
1974
1991
SetMultiXactIdLimit (MultiXactId oldest_datminmxid , Oid oldest_datoid )
1975
1992
{
1976
1993
MultiXactId multiVacLimit ;
1977
- MultiXactId multiWarnLimit ;
1978
- MultiXactId multiStopLimit ;
1979
- MultiXactId multiWrapLimit ;
1980
- MultiXactId curMulti ;
1981
1994
1982
1995
Assert (MultiXactIdIsValid (oldest_datminmxid ));
1983
1996
1984
- /*
1985
- * We pretend that a wrap will happen halfway through the multixact ID
1986
- * space, but that's not really true, because multixacts wrap differently
1987
- * from transaction IDs. Note that, separately from any concern about
1988
- * multixact IDs wrapping, we must ensure that multixact members do not
1989
- * wrap. Limits for that are set in DetermineSafeOldestOffset, not here.
1990
- */
1991
- multiWrapLimit = oldest_datminmxid + (MaxMultiXactId >> 1 );
1992
- if (multiWrapLimit < FirstMultiXactId )
1993
- multiWrapLimit += FirstMultiXactId ;
1994
-
1995
- /*
1996
- * We'll refuse to continue assigning MultiXactIds once we get within 100
1997
- * multi of data loss.
1998
- *
1999
- * Note: This differs from the magic number used in
2000
- * SetTransactionIdLimit() since vacuum itself will never generate new
2001
- * multis. XXX actually it does, if it needs to freeze old multis.
2002
- */
2003
- multiStopLimit = multiWrapLimit - 100 ;
2004
- if (multiStopLimit < FirstMultiXactId )
2005
- multiStopLimit -= FirstMultiXactId ;
2006
-
2007
- /*
2008
- * We'll start complaining loudly when we get within 10M multis of the
2009
- * stop point. This is kind of arbitrary, but if you let your gas gauge
2010
- * get down to 1% of full, would you be looking for the next gas station?
2011
- * We need to be fairly liberal about this number because there are lots
2012
- * of scenarios where most transactions are done by automatic clients that
2013
- * won't pay attention to warnings. (No, we're not gonna make this
2014
- * configurable. If you know enough to configure it, you know enough to
2015
- * not get in this kind of trouble in the first place.)
2016
- */
2017
- multiWarnLimit = multiStopLimit - 10000000 ;
2018
- if (multiWarnLimit < FirstMultiXactId )
2019
- multiWarnLimit -= FirstMultiXactId ;
2020
-
2021
1997
/*
2022
1998
* We'll start trying to force autovacuums when oldest_datminmxid gets to
2023
1999
* be more than autovacuum_multixact_freeze_max_age mxids old.
@@ -2027,25 +2003,14 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
2027
2003
* its value. See SetTransactionIdLimit.
2028
2004
*/
2029
2005
multiVacLimit = oldest_datminmxid + autovacuum_multixact_freeze_max_age ;
2030
- if (multiVacLimit < FirstMultiXactId )
2031
- multiVacLimit += FirstMultiXactId ;
2032
2006
2033
2007
/* Grab lock for just long enough to set the new limit values */
2034
2008
LWLockAcquire (MultiXactGenLock , LW_EXCLUSIVE );
2035
2009
MultiXactState -> oldestMultiXactId = oldest_datminmxid ;
2036
2010
MultiXactState -> oldestMultiXactDB = oldest_datoid ;
2037
2011
MultiXactState -> multiVacLimit = multiVacLimit ;
2038
- MultiXactState -> multiWarnLimit = multiWarnLimit ;
2039
- MultiXactState -> multiStopLimit = multiStopLimit ;
2040
- MultiXactState -> multiWrapLimit = multiWrapLimit ;
2041
- curMulti = MultiXactState -> nextMXact ;
2042
2012
LWLockRelease (MultiXactGenLock );
2043
2013
2044
- /* Log the info */
2045
- ereport (DEBUG1 ,
2046
- (errmsg ("MultiXactId wrap limit is " XID_FMT ", limited by database with OID %u" ,
2047
- multiWrapLimit , oldest_datoid )));
2048
-
2049
2014
/*
2050
2015
* Computing the actual limits is only possible once the data directory is
2051
2016
* in a consistent state. There's no need to compute the limits while
@@ -2285,35 +2250,6 @@ find_multixact_start(MultiXactId multi, MultiXactOffset *result)
2285
2250
return true;
2286
2251
}
2287
2252
2288
- /*
2289
- * Determine how many multixacts, and how many multixact members, currently
2290
- * exist. Return false if unable to determine.
2291
- */
2292
- static bool
2293
- ReadMultiXactCounts (uint64 * multixacts , MultiXactOffset * members )
2294
- {
2295
- MultiXactOffset nextOffset ;
2296
- MultiXactOffset oldestOffset ;
2297
- MultiXactId oldestMultiXactId ;
2298
- MultiXactId nextMultiXactId ;
2299
- bool oldestOffsetKnown ;
2300
-
2301
- LWLockAcquire (MultiXactGenLock , LW_SHARED );
2302
- nextOffset = MultiXactState -> nextOffset ;
2303
- oldestMultiXactId = MultiXactState -> oldestMultiXactId ;
2304
- nextMultiXactId = MultiXactState -> nextMXact ;
2305
- oldestOffset = MultiXactState -> oldestOffset ;
2306
- oldestOffsetKnown = MultiXactState -> oldestOffsetKnown ;
2307
- LWLockRelease (MultiXactGenLock );
2308
-
2309
- if (!oldestOffsetKnown )
2310
- return false;
2311
-
2312
- * members = nextOffset - oldestOffset ;
2313
- * multixacts = nextMultiXactId - oldestMultiXactId ;
2314
- return true;
2315
- }
2316
-
2317
2253
typedef struct mxtruncinfo
2318
2254
{
2319
2255
int earliestExistingPage ;
0 commit comments