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

Commit4cd3fb6

Browse files
committed
Truncate predicate lock manager's SLRU lazily at checkpoint. That's safer
than doing it aggressively whenever the tail-XID pointer is advanced, becausethis way we don't need to do it while holding SerializableXactHashLock.This also fixes bug #5915 spotted by YAMAMOTO Takashi, and removes anobsolete comment spotted by Kevin Grittner.
1 parent804d13a commit4cd3fb6

File tree

3 files changed

+69
-52
lines changed

3 files changed

+69
-52
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include"storage/ipc.h"
4949
#include"storage/latch.h"
5050
#include"storage/pmsignal.h"
51+
#include"storage/predicate.h"
5152
#include"storage/procarray.h"
5253
#include"storage/reinit.h"
5354
#include"storage/smgr.h"
@@ -7875,6 +7876,7 @@ CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
78757876
CheckPointCLOG();
78767877
CheckPointSUBTRANS();
78777878
CheckPointMultiXact();
7879+
CheckPointPredicate();
78787880
CheckPointRelationMap();
78797881
CheckPointBuffers(flags);/* performs all required fsyncs */
78807882
/* We deliberately delay 2PC checkpointing as long as possible */

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

Lines changed: 65 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,9 @@ static SlruCtlData OldSerXidSlruCtlData;
323323

324324
typedefstructOldSerXidControlData
325325
{
326-
intheadPage;
327-
inttailSegment;
328-
TransactionIdheadXid;
329-
TransactionIdtailXid;
326+
intheadPage;/* newest initialized page */
327+
TransactionIdheadXid;/* newest valid Xid in the SLRU */
328+
TransactionIdtailXid;/* oldest xmin we might be interested in */
330329
boolwarningIssued;
331330
}OldSerXidControlData;
332331

@@ -711,7 +710,6 @@ OldSerXidInit(void)
711710
* Set control information to reflect empty SLRU.
712711
*/
713712
oldSerXidControl->headPage=-1;
714-
oldSerXidControl->tailSegment=-1;
715713
oldSerXidControl->headXid=InvalidTransactionId;
716714
oldSerXidControl->tailXid=InvalidTransactionId;
717715
oldSerXidControl->warningIssued= false;
@@ -722,18 +720,14 @@ OldSerXidInit(void)
722720
* Record a committed read write serializable xid and the minimum
723721
* commitSeqNo of any transactions to which this xid had a rw-conflict out.
724722
* A zero seqNo means that there were no conflicts out from xid.
725-
*
726-
* The return value is normally false -- true means that we're about to
727-
* wrap around our space for tracking these xids, so the caller might want
728-
* to take action to prevent that.
729723
*/
730724
staticvoid
731725
OldSerXidAdd(TransactionIdxid,SerCommitSeqNominConflictCommitSeqNo)
732726
{
733727
TransactionIdtailXid;
734728
inttargetPage;
735729
intslotno;
736-
intpage;
730+
intfirstZeroPage;
737731
intxidSpread;
738732
boolisNewPage;
739733

@@ -745,30 +739,34 @@ OldSerXidAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
745739

746740
/*
747741
* If no serializable transactions are active, there shouldn't be anything
748-
* to push out tothis SLRU. Hitting this assert would mean there's
742+
* to push out tothe SLRU. Hitting this assert would mean there's
749743
* something wrong with the earlier cleanup logic.
750744
*/
751745
tailXid=oldSerXidControl->tailXid;
752746
Assert(TransactionIdIsValid(tailXid));
753747

748+
/*
749+
* If the SLRU is currently unused, zero out the whole active region
750+
* from tailXid to headXid before taking it into use. Otherwise zero
751+
* out only any new pages that enter the tailXid-headXid range as we
752+
* advance headXid.
753+
*/
754754
if (oldSerXidControl->headPage<0)
755755
{
756-
page=OldSerXidPage(tailXid);
757-
oldSerXidControl->tailSegment=OldSerXidSegment(page);
758-
page=oldSerXidControl->tailSegment*OLDSERXID_ENTRIESPERPAGE;
756+
firstZeroPage=OldSerXidPage(tailXid);
759757
isNewPage= true;
760758
}
761759
else
762760
{
763-
page=OldSerXidNextPage(oldSerXidControl->headPage);
764-
isNewPage=OldSerXidPagePrecedesLogically(oldSerXidControl->headPage,targetPage);
761+
firstZeroPage=OldSerXidNextPage(oldSerXidControl->headPage);
762+
isNewPage=OldSerXidPagePrecedesLogically(oldSerXidControl->headPage,
763+
targetPage);
765764
}
766765

767766
if (!TransactionIdIsValid(oldSerXidControl->headXid)
768767
||TransactionIdFollows(xid,oldSerXidControl->headXid))
769768
oldSerXidControl->headXid=xid;
770-
if (oldSerXidControl->headPage<0
771-
||OldSerXidPagePrecedesLogically(oldSerXidControl->headPage,targetPage))
769+
if (isNewPage)
772770
oldSerXidControl->headPage=targetPage;
773771

774772
xidSpread= (((uint32)xid)- ((uint32)tailXid));
@@ -788,10 +786,10 @@ OldSerXidAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
788786
if (isNewPage)
789787
{
790788
/* Initialize intervening pages. */
791-
while (page!=targetPage)
789+
while (firstZeroPage!=targetPage)
792790
{
793-
(void)SimpleLruZeroPage(OldSerXidSlruCtl,page);
794-
page=OldSerXidNextPage(page);
791+
(void)SimpleLruZeroPage(OldSerXidSlruCtl,firstZeroPage);
792+
firstZeroPage=OldSerXidNextPage(firstZeroPage);
795793
}
796794
slotno=SimpleLruZeroPage(OldSerXidSlruCtl,targetPage);
797795
}
@@ -846,31 +844,24 @@ OldSerXidGetMinConflictCommitSeqNo(TransactionId xid)
846844
/*
847845
* Call this whenever there is a new xmin for active serializable
848846
* transactions. We don't need to keep information on transactions which
849-
*preceed that. InvalidTransactionId means none active, so everything in
850-
* the SLRUshould be discarded.
847+
*precede that. InvalidTransactionId means none active, so everything in
848+
* the SLRUcan be discarded.
851849
*/
852850
staticvoid
853851
OldSerXidSetActiveSerXmin(TransactionIdxid)
854852
{
855-
intnewTailPage;
856-
intnewTailSegment;
857-
858853
LWLockAcquire(OldSerXidLock,LW_EXCLUSIVE);
859854

860855
/*
861856
* When no sxacts are active, nothing overlaps, set the xid values to
862-
* invalid to show that there are no valid entries. Don't clear the
863-
* segment/page information, though. A new xmin might still land in an
864-
* existing segment, and we don't want to repeatedly delete and re-create
865-
* the same segment file.
857+
* invalid to show that there are no valid entries. Don't clear headPage,
858+
* though. A new xmin might still land on that page, and we don't want
859+
* to repeatedly zero out the same page.
866860
*/
867861
if (!TransactionIdIsValid(xid))
868862
{
869-
if (TransactionIdIsValid(oldSerXidControl->tailXid))
870-
{
871-
oldSerXidControl->headXid=InvalidTransactionId;
872-
oldSerXidControl->tailXid=InvalidTransactionId;
873-
}
863+
oldSerXidControl->tailXid=InvalidTransactionId;
864+
oldSerXidControl->headXid=InvalidTransactionId;
874865
LWLockRelease(OldSerXidLock);
875866
return;
876867
}
@@ -886,7 +877,9 @@ OldSerXidSetActiveSerXmin(TransactionId xid)
886877
Assert(oldSerXidControl->headPage<0);
887878
if (!TransactionIdIsValid(oldSerXidControl->tailXid)
888879
||TransactionIdPrecedes(xid,oldSerXidControl->tailXid))
880+
{
889881
oldSerXidControl->tailXid=xid;
882+
}
890883
LWLockRelease(OldSerXidLock);
891884
return;
892885
}
@@ -896,37 +889,57 @@ OldSerXidSetActiveSerXmin(TransactionId xid)
896889

897890
oldSerXidControl->tailXid=xid;
898891

899-
/* Exit quickly if there are no segments active. */
892+
LWLockRelease(OldSerXidLock);
893+
}
894+
895+
/*
896+
* Perform a checkpoint --- either during shutdown, or on-the-fly
897+
*
898+
* We don't have any data that needs to survive a restart, but this is a
899+
* convenient place to truncate the SLRU.
900+
*/
901+
void
902+
CheckPointPredicate(void)
903+
{
904+
inttailPage;
905+
906+
LWLockAcquire(OldSerXidLock,LW_EXCLUSIVE);
907+
908+
/* Exit quickly if the SLRU is currently not in use. */
900909
if (oldSerXidControl->headPage<0)
901910
{
902911
LWLockRelease(OldSerXidLock);
903912
return;
904913
}
905914

906-
newTailPage=OldSerXidPage(xid);
907-
newTailSegment=OldSerXidSegment(newTailPage);
908-
909-
/* Exit quickly if we're still on the same segment. */
910-
if (newTailSegment==oldSerXidControl->tailSegment)
915+
if (TransactionIdIsValid(oldSerXidControl->tailXid))
911916
{
912-
LWLockRelease(OldSerXidLock);
913-
return;
917+
/* We can truncate the SLRU up to the page containing tailXid */
918+
tailPage=OldSerXidPage(oldSerXidControl->tailXid);
914919
}
915-
916-
oldSerXidControl->tailSegment=newTailSegment;
917-
918-
/* See if that has cleared the last segment. */
919-
if (OldSerXidPagePrecedesLogically(oldSerXidControl->headPage,
920-
newTailSegment*SLRU_PAGES_PER_SEGMENT))
920+
else
921921
{
922-
oldSerXidControl->headXid=InvalidTransactionId;
922+
/*
923+
* The SLRU is no longer needed. Truncate everything but the last
924+
* page. We don't dare to touch the last page in case the SLRU is
925+
* taken back to use, and the new tail falls on the same page.
926+
*/
927+
tailPage=oldSerXidControl->headPage;
923928
oldSerXidControl->headPage=-1;
924-
oldSerXidControl->tailSegment=-1;
925929
}
926930

927931
LWLockRelease(OldSerXidLock);
928932

929-
SimpleLruTruncate(OldSerXidSlruCtl,newTailPage);
933+
/*
934+
* Flush dirty SLRU pages to disk
935+
*
936+
* This is not actually necessary from a correctness point of view. We do
937+
* it merely as a debugging aid.
938+
*/
939+
SimpleLruFlush(OldSerXidSlruCtl, true);
940+
941+
/* Truncate away pages that are no longer required */
942+
SimpleLruTruncate(OldSerXidSlruCtl,tailPage);
930943
}
931944

932945
/*------------------------------------------------------------------------*/

‎src/include/storage/predicate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ extern intmax_predicate_locks_per_xact;
3636
externvoidInitPredicateLocks(void);
3737
externSizePredicateLockShmemSize(void);
3838

39+
externvoidCheckPointPredicate(void);
40+
3941
/* predicate lock reporting */
4042
externboolPageIsPredicateLocked(constRelationrelation,constBlockNumberblkno);
4143

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp