96
96
/*
97
97
* Defines for MultiXactOffset page sizes. A page is the same BLCKSZ as is
98
98
* used everywhere else in Postgres.
99
- *
100
- * Note: because MultiXactOffsets are 32 bits and wrap around at 0xFFFFFFFF,
101
- * MultiXact page numbering also wraps around at
102
- * 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE, and segment numbering at
103
- * 0xFFFFFFFF/MULTIXACT_OFFSETS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need
104
- * take no explicit notice of that fact in this module, except when comparing
105
- * segment and page numbers in TruncateMultiXact (see
106
- * MultiXactOffsetPagePrecedes).
107
99
*/
108
100
109
101
/* We need four bytes per offset */
@@ -272,9 +264,6 @@ typedef struct MultiXactStateData
272
264
MultiXactId multiStopLimit ;
273
265
MultiXactId multiWrapLimit ;
274
266
275
- /* support for members anti-wraparound measures */
276
- MultiXactOffset offsetStopLimit ; /* known if oldestOffsetKnown */
277
-
278
267
/*
279
268
* This is used to sleep until a multixact offset is written when we want
280
269
* to create the next one.
@@ -409,8 +398,6 @@ static bool MultiXactOffsetPrecedes(MultiXactOffset offset1,
409
398
MultiXactOffset offset2 );
410
399
static void ExtendMultiXactOffset (MultiXactId multi );
411
400
static void ExtendMultiXactMember (MultiXactOffset offset , int nmembers );
412
- static bool MultiXactOffsetWouldWrap (MultiXactOffset boundary ,
413
- MultiXactOffset start , uint32 distance );
414
401
static bool SetOffsetVacuumLimit (bool is_startup );
415
402
static bool find_multixact_start (MultiXactId multi , MultiXactOffset * result );
416
403
static void WriteMZeroPageXlogRec (int64 pageno , uint8 info );
@@ -1164,78 +1151,6 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
1164
1151
else
1165
1152
* offset = nextOffset ;
1166
1153
1167
- /*----------
1168
- * Protect against overrun of the members space as well, with the
1169
- * following rules:
1170
- *
1171
- * If we're past offsetStopLimit, refuse to generate more multis.
1172
- * If we're close to offsetStopLimit, emit a warning.
1173
- *
1174
- * Arbitrarily, we start emitting warnings when we're 20 segments or less
1175
- * from offsetStopLimit.
1176
- *
1177
- * Note we haven't updated the shared state yet, so if we fail at this
1178
- * point, the multixact ID we grabbed can still be used by the next guy.
1179
- *
1180
- * Note that there is no point in forcing autovacuum runs here: the
1181
- * multixact freeze settings would have to be reduced for that to have any
1182
- * effect.
1183
- *----------
1184
- */
1185
- #define OFFSET_WARN_SEGMENTS 20
1186
- if (MultiXactState -> oldestOffsetKnown &&
1187
- MultiXactOffsetWouldWrap (MultiXactState -> offsetStopLimit , nextOffset ,
1188
- nmembers ))
1189
- {
1190
- /* see comment in the corresponding offsets wraparound case */
1191
- SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_LAUNCHER );
1192
-
1193
- ereport (ERROR ,
1194
- (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
1195
- errmsg ("multixact \"members\" limit exceeded" ),
1196
- errdetail_plural ("This command would create a multixact with %u members, but the remaining space is only enough for %u member." ,
1197
- "This command would create a multixact with %u members, but the remaining space is only enough for %u members." ,
1198
- MultiXactState -> offsetStopLimit - nextOffset - 1 ,
1199
- nmembers ,
1200
- MultiXactState -> offsetStopLimit - nextOffset - 1 ),
1201
- errhint ("Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." ,
1202
- MultiXactState -> oldestMultiXactDB )));
1203
- }
1204
-
1205
- /*
1206
- * Check whether we should kick autovacuum into action, to prevent members
1207
- * wraparound. NB we use a much larger window to trigger autovacuum than
1208
- * just the warning limit. The warning is just a measure of last resort -
1209
- * this is in line with GetNewTransactionId's behaviour.
1210
- */
1211
- if (!MultiXactState -> oldestOffsetKnown ||
1212
- (MultiXactState -> nextOffset - MultiXactState -> oldestOffset
1213
- > MULTIXACT_MEMBER_SAFE_THRESHOLD ))
1214
- {
1215
- /*
1216
- * To avoid swamping the postmaster with signals, we issue the autovac
1217
- * request only when crossing a segment boundary. With default
1218
- * compilation settings that's roughly after 50k members. This still
1219
- * gives plenty of chances before we get into real trouble.
1220
- */
1221
- if ((MXOffsetToMemberPage (nextOffset ) / SLRU_PAGES_PER_SEGMENT ) !=
1222
- (MXOffsetToMemberPage (nextOffset + nmembers ) / SLRU_PAGES_PER_SEGMENT ))
1223
- SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_LAUNCHER );
1224
- }
1225
-
1226
- if (MultiXactState -> oldestOffsetKnown &&
1227
- MultiXactOffsetWouldWrap (MultiXactState -> offsetStopLimit ,
1228
- nextOffset ,
1229
- nmembers + MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT * OFFSET_WARN_SEGMENTS ))
1230
- ereport (WARNING ,
1231
- (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
1232
- errmsg_plural ("database with OID %u must be vacuumed before %d more multixact member is used" ,
1233
- "database with OID %u must be vacuumed before %d more multixact members are used" ,
1234
- MultiXactState -> offsetStopLimit - nextOffset + nmembers ,
1235
- MultiXactState -> oldestMultiXactDB ,
1236
- MultiXactState -> offsetStopLimit - nextOffset + nmembers ),
1237
- errhint ("Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." )));
1238
-
1239
1154
ExtendMultiXactMember (nextOffset , nmembers );
1240
1155
1241
1156
/*
@@ -2720,8 +2635,6 @@ SetOffsetVacuumLimit(bool is_startup)
2720
2635
MultiXactOffset nextOffset ;
2721
2636
bool oldestOffsetKnown = false;
2722
2637
bool prevOldestOffsetKnown ;
2723
- MultiXactOffset offsetStopLimit = 0 ;
2724
- MultiXactOffset prevOffsetStopLimit ;
2725
2638
2726
2639
/*
2727
2640
* NB: Have to prevent concurrent truncation, we might otherwise try to
@@ -2736,7 +2649,6 @@ SetOffsetVacuumLimit(bool is_startup)
2736
2649
nextOffset = MultiXactState -> nextOffset ;
2737
2650
prevOldestOffsetKnown = MultiXactState -> oldestOffsetKnown ;
2738
2651
prevOldestOffset = MultiXactState -> oldestOffset ;
2739
- prevOffsetStopLimit = MultiXactState -> offsetStopLimit ;
2740
2652
Assert (MultiXactState -> finishedStartup );
2741
2653
LWLockRelease (MultiXactGenLock );
2742
2654
@@ -2767,11 +2679,7 @@ SetOffsetVacuumLimit(bool is_startup)
2767
2679
oldestOffsetKnown =
2768
2680
find_multixact_start (oldestMultiXactId , & oldestOffset );
2769
2681
2770
- if (oldestOffsetKnown )
2771
- ereport (DEBUG1 ,
2772
- (errmsg_internal ("oldest MultiXactId member is at offset %u" ,
2773
- oldestOffset )));
2774
- else
2682
+ if (!oldestOffsetKnown )
2775
2683
ereport (LOG ,
2776
2684
(errmsg ("MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" ,
2777
2685
oldestMultiXactId )));
@@ -2784,24 +2692,7 @@ SetOffsetVacuumLimit(bool is_startup)
2784
2692
* overrun of old data in the members SLRU area. We can only do so if the
2785
2693
* oldest offset is known though.
2786
2694
*/
2787
- if (oldestOffsetKnown )
2788
- {
2789
- /* move back to start of the corresponding segment */
2790
- offsetStopLimit = oldestOffset - (oldestOffset %
2791
- (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT ));
2792
-
2793
- /* always leave one segment before the wraparound point */
2794
- offsetStopLimit -= (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT );
2795
-
2796
- if (!prevOldestOffsetKnown && !is_startup )
2797
- ereport (LOG ,
2798
- (errmsg ("MultiXact member wraparound protections are now enabled" )));
2799
-
2800
- ereport (DEBUG1 ,
2801
- (errmsg_internal ("MultiXact member stop limit is now %u based on MultiXact %u" ,
2802
- offsetStopLimit , oldestMultiXactId )));
2803
- }
2804
- else if (prevOldestOffsetKnown )
2695
+ if (prevOldestOffsetKnown )
2805
2696
{
2806
2697
/*
2807
2698
* If we failed to get the oldest offset this time, but we have a
@@ -2811,14 +2702,12 @@ SetOffsetVacuumLimit(bool is_startup)
2811
2702
*/
2812
2703
oldestOffset = prevOldestOffset ;
2813
2704
oldestOffsetKnown = true;
2814
- offsetStopLimit = prevOffsetStopLimit ;
2815
2705
}
2816
2706
2817
2707
/* Install the computed values */
2818
2708
LWLockAcquire (MultiXactGenLock , LW_EXCLUSIVE );
2819
2709
MultiXactState -> oldestOffset = oldestOffset ;
2820
2710
MultiXactState -> oldestOffsetKnown = oldestOffsetKnown ;
2821
- MultiXactState -> offsetStopLimit = offsetStopLimit ;
2822
2711
LWLockRelease (MultiXactGenLock );
2823
2712
2824
2713
/*
@@ -2828,54 +2717,6 @@ SetOffsetVacuumLimit(bool is_startup)
2828
2717
(nextOffset - oldestOffset > MULTIXACT_MEMBER_SAFE_THRESHOLD );
2829
2718
}
2830
2719
2831
- /*
2832
- * Return whether adding "distance" to "start" would move past "boundary".
2833
- *
2834
- * We use this to determine whether the addition is "wrapping around" the
2835
- * boundary point, hence the name. The reason we don't want to use the regular
2836
- * 2^31-modulo arithmetic here is that we want to be able to use the whole of
2837
- * the 2^32-1 space here, allowing for more multixacts than would fit
2838
- * otherwise.
2839
- */
2840
- static bool
2841
- MultiXactOffsetWouldWrap (MultiXactOffset boundary , MultiXactOffset start ,
2842
- uint32 distance )
2843
- {
2844
- MultiXactOffset finish ;
2845
-
2846
- /*
2847
- * Note that offset number 0 is not used (see GetMultiXactIdMembers), so
2848
- * if the addition wraps around the UINT_MAX boundary, skip that value.
2849
- */
2850
- finish = start + distance ;
2851
- if (finish < start )
2852
- finish ++ ;
2853
-
2854
- /*-----------------------------------------------------------------------
2855
- * When the boundary is numerically greater than the starting point, any
2856
- * value numerically between the two is not wrapped:
2857
- *
2858
- * <----S----B---->
2859
- * [---) = F wrapped past B (and UINT_MAX)
2860
- * [---) = F not wrapped
2861
- * [----] = F wrapped past B
2862
- *
2863
- * When the boundary is numerically less than the starting point (i.e. the
2864
- * UINT_MAX wraparound occurs somewhere in between) then all values in
2865
- * between are wrapped:
2866
- *
2867
- * <----B----S---->
2868
- * [---) = F not wrapped past B (but wrapped past UINT_MAX)
2869
- * [---) = F wrapped past B (and UINT_MAX)
2870
- * [----] = F not wrapped
2871
- *-----------------------------------------------------------------------
2872
- */
2873
- if (start < boundary )
2874
- return finish >= boundary || finish < start ;
2875
- else
2876
- return finish >= boundary && finish < start ;
2877
- }
2878
-
2879
2720
/*
2880
2721
* Find the starting offset of the given MultiXactId.
2881
2722
*
@@ -2997,8 +2838,9 @@ MultiXactMemberFreezeThreshold(void)
2997
2838
* we try to eliminate from the system is based on how far we are past
2998
2839
* MULTIXACT_MEMBER_SAFE_THRESHOLD.
2999
2840
*/
3000
- fraction = (double ) (members - MULTIXACT_MEMBER_SAFE_THRESHOLD ) /
3001
- (MULTIXACT_MEMBER_DANGER_THRESHOLD - MULTIXACT_MEMBER_SAFE_THRESHOLD );
2841
+ fraction = (double ) (members - MULTIXACT_MEMBER_SAFE_THRESHOLD );
2842
+ fraction /= (double ) (MULTIXACT_MEMBER_DANGER_THRESHOLD - MULTIXACT_MEMBER_SAFE_THRESHOLD );
2843
+
3002
2844
victim_multixacts = multixacts * fraction ;
3003
2845
3004
2846
/* fraction could be > 1.0, but lowest possible freeze age is zero */
@@ -3343,7 +3185,7 @@ MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
3343
3185
static bool
3344
3186
MultiXactOffsetPrecedes (MultiXactOffset offset1 , MultiXactOffset offset2 )
3345
3187
{
3346
- int32 diff = (int32 ) (offset1 - offset2 );
3188
+ int64 diff = (int64 ) (offset1 - offset2 );
3347
3189
3348
3190
return (diff < 0 );
3349
3191
}
0 commit comments