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

Commite1c26ab

Browse files
committed
Fix the truncation logic of the OldSerXid SLRU mechanism. We can't pass
SimpleLruTruncate() a page number that's "in the future", because it willissue a warning and refuse to truncate anything. Instead, we leave behindthe latest segment. If the slru is not needed before XID wrap-around, thesegment will appear as new again, and not be cleaned up until it gets oldenough again. That's a bit unpleasant, but better than not cleaning upanything.Also, fix broken calculation to check and warn if the span of the OldSerXidSLRU is getting too large to fit in the 64k SLRU pages that we haveavailable. It was not XID wraparound aware.Kevin Grittner and me.
1 parent6560407 commite1c26ab

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

‎src/backend/storage/lmgr/predicate.c

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ typedef struct OldSerXidControlData
330330
intheadPage;/* newest initialized page */
331331
TransactionIdheadXid;/* newest valid Xid in the SLRU */
332332
TransactionIdtailXid;/* oldest xmin we might be interested in */
333-
boolwarningIssued;
333+
boolwarningIssued;/* have we issued SLRU wrap-around warning? */
334334
}OldSerXidControlData;
335335

336336
typedefstructOldSerXidControlData*OldSerXidControl;
@@ -738,7 +738,6 @@ OldSerXidAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
738738
inttargetPage;
739739
intslotno;
740740
intfirstZeroPage;
741-
intxidSpread;
742741
boolisNewPage;
743742

744743
Assert(TransactionIdIsValid(xid));
@@ -779,18 +778,45 @@ OldSerXidAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
779778
if (isNewPage)
780779
oldSerXidControl->headPage=targetPage;
781780

782-
xidSpread= (((uint32)xid)- ((uint32)tailXid));
781+
/*
782+
* Give a warning if we're about to run out of SLRU pages.
783+
*
784+
* slru.c has a maximum of 64k segments, with 32 (SLRU_PAGES_PER_SEGMENT)
785+
* pages each. We need to store a 64-bit integer for each Xid, and with
786+
* default 8k block size, 65536*32 pages is only enough to cover 2^30
787+
* XIDs. If we're about to hit that limit and wrap around, warn the user.
788+
*
789+
* To avoid spamming the user, we only give one warning when we've used 1
790+
* billion XIDs, and stay silent until the situation is fixed and the
791+
* number of XIDs used falls below 800 million again.
792+
*
793+
* XXX: We have no safeguard to actually *prevent* the wrap-around,
794+
* though. All you get is a warning.
795+
*/
783796
if (oldSerXidControl->warningIssued)
784797
{
785-
if (xidSpread<800000000)
798+
TransactionIdlowWatermark;
799+
800+
lowWatermark=tailXid+800000000;
801+
if (lowWatermark<FirstNormalTransactionId)
802+
lowWatermark=FirstNormalTransactionId;
803+
if (TransactionIdPrecedes(xid,lowWatermark))
786804
oldSerXidControl->warningIssued= false;
787805
}
788-
elseif (xidSpread >=1000000000)
806+
else
789807
{
790-
oldSerXidControl->warningIssued= true;
791-
ereport(WARNING,
792-
(errmsg("memory for serializable conflict tracking is nearly exhausted"),
793-
errhint("There may be an idle transaction or a forgotten prepared transaction causing this.")));
808+
TransactionIdhighWatermark;
809+
810+
highWatermark=tailXid+1000000000;
811+
if (highWatermark<FirstNormalTransactionId)
812+
highWatermark=FirstNormalTransactionId;
813+
if (TransactionIdFollows(xid,highWatermark))
814+
{
815+
oldSerXidControl->warningIssued= true;
816+
ereport(WARNING,
817+
(errmsg("memory for serializable conflict tracking is nearly exhausted"),
818+
errhint("There may be an idle transaction or a forgotten prepared transaction causing this.")));
819+
}
794820
}
795821

796822
if (isNewPage)
@@ -931,18 +957,16 @@ CheckPointPredicate(void)
931957
else
932958
{
933959
/*
934-
* The SLRU is no longer needed. Truncate everything. If we try to
935-
* leave the head page around to avoid re-zeroing it, we might not use
936-
* the SLRU again until we're past the wrap-around point, which makes
937-
* SLRU unhappy.
960+
* The SLRU is no longer needed. Truncate to head before we set head
961+
* invalid.
938962
*
939-
*While the API asks you to specify truncation by page, it silently
940-
*ignores the request unlessthespecified page is in asegmentpast
941-
*some allocated portion of the SLRU.We don't care which page in a
942-
*later segment we hit, so just add the number of pages per segment
943-
*to the head page to land us *somewhere* in the next segment.
963+
*XXX: It's possible that the SLRU is not needed again until XID
964+
*wrap-around has happened, so thatthe segmentcontaining headPage
965+
*that we leave behind will appear to be new again. In that case it
966+
*won't be removed until XID horizon advances enough to make it
967+
*current again.
944968
*/
945-
tailPage=oldSerXidControl->headPage+SLRU_PAGES_PER_SEGMENT;
969+
tailPage=oldSerXidControl->headPage;
946970
oldSerXidControl->headPage=-1;
947971
}
948972

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp