Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8ec1a3a

Browse files
committed
Even when autovacuum=off, force it for members as we do in other cases.
Thomas Munro, with some adjustments by me.
1 parentded8919 commit8ec1a3a

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

‎src/backend/access/transam/multixact.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ typedef struct MultiXactStateData
202202
*/
203203
MultiXactIdoldestMultiXactId;
204204
OidoldestMultiXactDB;
205+
MultiXactOffsetoldestOffset;
205206

206207
/*
207208
* This is what the previous checkpoint stored as the truncate position.
@@ -959,14 +960,17 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
959960
* against catastrophic data loss due to multixact wraparound. The basic
960961
* rules are:
961962
*
962-
* If we're past multiVacLimit, start trying to force autovacuum cycles.
963+
* If we're past multiVacLimit or the safe threshold for member storage space,
964+
* start trying to force autovacuum cycles.
963965
* If we're past multiWarnLimit, start issuing warnings.
964966
* If we're past multiStopLimit, refuse to create new MultiXactIds.
965967
*
966968
* Note these are pretty much the same protections in GetNewTransactionId.
967969
*----------
968970
*/
969-
if (!MultiXactIdPrecedes(result,MultiXactState->multiVacLimit))
971+
if (!MultiXactIdPrecedes(result,MultiXactState->multiVacLimit)||
972+
(MultiXactState->nextOffset-MultiXactState->oldestOffset
973+
>MULTIXACT_MEMBER_SAFE_THRESHOLD))
970974
{
971975
/*
972976
* For safety's sake, we release MultiXactGenLock while sending
@@ -2161,6 +2165,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
21612165
MultiXactIdmultiStopLimit;
21622166
MultiXactIdmultiWrapLimit;
21632167
MultiXactIdcurMulti;
2168+
MultiXactOffsetoldestOffset;
2169+
MultiXactOffsetnextOffset;
21642170

21652171
Assert(MultiXactIdIsValid(oldest_datminmxid));
21662172

@@ -2213,6 +2219,35 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
22132219
if (multiVacLimit<FirstMultiXactId)
22142220
multiVacLimit+=FirstMultiXactId;
22152221

2222+
/*
2223+
* Determine the offset of the oldest multixact that might still be
2224+
* referenced. Normally, we can read the offset from the multixact itself,
2225+
* but there's an important special case: if there are no multixacts in
2226+
* existence at all, oldest_datminmxid obviously can't point to one. It
2227+
* will instead point to the multixact ID that will be assigned the next
2228+
* time one is needed.
2229+
*
2230+
* NB: oldest_dataminmxid is the oldest multixact that might still be
2231+
* referenced from a table, unlike in DetermineSafeOldestOffset, where we
2232+
* do this same computation based on the oldest value that might still
2233+
* exist in the SLRU. This is because here we're trying to compute a
2234+
* threshold for activating autovacuum, which can only remove references
2235+
* to multixacts, whereas there we are computing a threshold for creating
2236+
* new multixacts, which requires the old ones to have first been
2237+
* truncated away by a checkpoint.
2238+
*/
2239+
LWLockAcquire(MultiXactGenLock,LW_SHARED);
2240+
if (MultiXactState->nextMXact==oldest_datminmxid)
2241+
{
2242+
oldestOffset=MultiXactState->nextOffset;
2243+
LWLockRelease(MultiXactGenLock);
2244+
}
2245+
else
2246+
{
2247+
LWLockRelease(MultiXactGenLock);
2248+
oldestOffset=find_multixact_start(oldest_datminmxid);
2249+
}
2250+
22162251
/* Grab lock for just long enough to set the new limit values */
22172252
LWLockAcquire(MultiXactGenLock,LW_EXCLUSIVE);
22182253
MultiXactState->oldestMultiXactId=oldest_datminmxid;
@@ -2221,7 +2256,9 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
22212256
MultiXactState->multiWarnLimit=multiWarnLimit;
22222257
MultiXactState->multiStopLimit=multiStopLimit;
22232258
MultiXactState->multiWrapLimit=multiWrapLimit;
2259+
MultiXactState->oldestOffset=oldestOffset;
22242260
curMulti=MultiXactState->nextMXact;
2261+
nextOffset=MultiXactState->nextOffset;
22252262
LWLockRelease(MultiXactGenLock);
22262263

22272264
/* Log the info */
@@ -2236,7 +2273,8 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid)
22362273
* database, it'll call here, and we'll signal the postmaster to start
22372274
* another iteration immediately if there are still any old databases.
22382275
*/
2239-
if (MultiXactIdPrecedes(multiVacLimit,curMulti)&&
2276+
if ((MultiXactIdPrecedes(multiVacLimit,curMulti)||
2277+
(nextOffset-oldestOffset>MULTIXACT_MEMBER_SAFE_THRESHOLD))&&
22402278
IsUnderPostmaster&& !InRecovery)
22412279
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER);
22422280

@@ -2495,11 +2533,16 @@ DetermineSafeOldestOffset(MultiXactId oldestMXact)
24952533
MultiXactOffsetoldestOffset;
24962534

24972535
/*
2498-
* We determine the safe upper bound for offsets of new xacts by reading
2499-
* the offset of the oldest multixact, and going back one segment. This
2500-
* way, the sequence of multixact member segments will always have a
2501-
* one-segment hole at a minimum. We start spewing warnings a few
2502-
* complete segments before that.
2536+
* Determine the offset of the oldest multixact. Normally, we can read
2537+
* the offset from the multixact itself, but there's an important special
2538+
* case: if there are no multixacts in existence at all, oldestMXact
2539+
* obviously can't point to one. It will instead point to the multixact
2540+
* ID that will be assigned the next time one is needed.
2541+
*
2542+
* NB: oldestMXact should be the oldest multixact that still exists in
2543+
* the SLRU, unlike in SetMultiXactIdLimit, where we do this same
2544+
* computation based on the oldest value that might be referenced in a
2545+
* table.
25032546
*/
25042547
LWLockAcquire(MultiXactGenLock,LW_SHARED);
25052548
if (MultiXactState->nextMXact==oldestMXact)
@@ -2613,9 +2656,9 @@ ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
26132656
nextOffset=MultiXactState->nextOffset;
26142657
oldestMultiXactId=MultiXactState->oldestMultiXactId;
26152658
nextMultiXactId=MultiXactState->nextMXact;
2659+
oldestOffset=MultiXactState->oldestOffset;
26162660
LWLockRelease(MultiXactGenLock);
26172661

2618-
oldestOffset=find_multixact_start(oldestMultiXactId);
26192662
*members=nextOffset-oldestOffset;
26202663
*multixacts=nextMultiXactId-oldestMultiXactId;
26212664
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp