Skip to content

Commit 61b8614

Browse files
committed
Modify MoveOfflineLogs/InstallXLogFileSegment to avoid O(N^2) behavior
when recycling a large number of xlog segments during checkpoint. The former behavior searched from the same start point each time, requiring O(checkpoint_segments^2) stat() calls to relocate all the segments. Instead keep track of where we stopped last time through.
1 parent 348f856 commit 61b8614

File tree

1 file changed

+37
-23
lines changed
  • src/backend/access/transam

1 file changed

+37
-23
lines changed

src/backend/access/transam/xlog.c

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.184 2005/04/13 18:54:56 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.185 2005/04/15 18:48:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -444,8 +444,8 @@ static bool AdvanceXLInsertBuffer(void);
444444
static void XLogWrite(XLogwrtRqst WriteRqst);
445445
static int XLogFileInit(uint32 log, uint32 seg,
446446
bool *use_existent, bool use_lock);
447-
static bool InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath,
448-
bool find_free, int max_advance,
447+
static bool InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
448+
bool find_free, int *max_advance,
449449
bool use_lock);
450450
static int XLogFileOpen(uint32 log, uint32 seg);
451451
static int XLogFileRead(uint32 log, uint32 seg, int emode);
@@ -1509,6 +1509,9 @@ XLogFileInit(uint32 log, uint32 seg,
15091509
char path[MAXPGPATH];
15101510
char tmppath[MAXPGPATH];
15111511
char zbuffer[BLCKSZ];
1512+
uint32 installed_log;
1513+
uint32 installed_seg;
1514+
int max_advance;
15121515
int fd;
15131516
int nbytes;
15141517

@@ -1601,8 +1604,11 @@ XLogFileInit(uint32 log, uint32 seg,
16011604
* else has created the file while we were filling ours: if so, use
16021605
* ours to pre-create a future log segment.
16031606
*/
1604-
if (!InstallXLogFileSegment(log, seg, tmppath,
1605-
*use_existent, XLOGfileslop,
1607+
installed_log = log;
1608+
installed_seg = seg;
1609+
max_advance = XLOGfileslop;
1610+
if (!InstallXLogFileSegment(&installed_log, &installed_seg, tmppath,
1611+
*use_existent, &max_advance,
16061612
use_lock))
16071613
{
16081614
/* No need for any more future segments... */
@@ -1722,7 +1728,7 @@ XLogFileCopy(uint32 log, uint32 seg,
17221728
/*
17231729
* Now move the segment into place with its final name.
17241730
*/
1725-
if (!InstallXLogFileSegment(log, seg, tmppath, false, 0, false))
1731+
if (!InstallXLogFileSegment(&log, &seg, tmppath, false, NULL, false))
17261732
elog(PANIC, "InstallXLogFileSegment should not have failed");
17271733
}
17281734

@@ -1732,17 +1738,20 @@ XLogFileCopy(uint32 log, uint32 seg,
17321738
* This is used both to install a newly-created segment (which has a temp
17331739
* filename while it's being created) and to recycle an old segment.
17341740
*
1735-
* log, seg: identify segment to install as (or first possible target).
1741+
* *log, *seg: identify segment to install as (or first possible target).
1742+
* When find_free is TRUE, these are modified on return to indicate the
1743+
* actual installation location or last segment searched.
17361744
*
17371745
* tmppath: initial name of file to install. It will be renamed into place.
17381746
*
17391747
* find_free: if TRUE, install the new segment at the first empty log/seg
17401748
* number at or after the passed numbers. If FALSE, install the new segment
17411749
* exactly where specified, deleting any existing segment file there.
17421750
*
1743-
* max_advance: maximum number of log/seg slots to advance past the starting
1744-
* point. Fail if no free slot is found in this range. (Irrelevant if
1745-
* find_free is FALSE.)
1751+
* *max_advance: maximum number of log/seg slots to advance past the starting
1752+
* point. Fail if no free slot is found in this range. On return, reduced
1753+
* by the number of slots skipped over. (Irrelevant, and may be NULL,
1754+
* when find_free is FALSE.)
17461755
*
17471756
* use_lock: if TRUE, acquire ControlFileLock while moving file into
17481757
* place. This should be TRUE except during bootstrap log creation. The
@@ -1752,14 +1761,14 @@ XLogFileCopy(uint32 log, uint32 seg,
17521761
* exceeding max_advance limit. (Any other kind of failure causes ereport().)
17531762
*/
17541763
static bool
1755-
InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath,
1756-
bool find_free, int max_advance,
1764+
InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
1765+
bool find_free, int *max_advance,
17571766
bool use_lock)
17581767
{
17591768
char path[MAXPGPATH];
17601769
struct stat stat_buf;
17611770

1762-
XLogFilePath(path, ThisTimeLineID, log, seg);
1771+
XLogFilePath(path, ThisTimeLineID, *log, *seg);
17631772

17641773
/*
17651774
* We want to be sure that only one process does this at a time.
@@ -1777,15 +1786,16 @@ InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath,
17771786
/* Find a free slot to put it in */
17781787
while (stat(path, &stat_buf) == 0)
17791788
{
1780-
if (--max_advance < 0)
1789+
if (*max_advance <= 0)
17811790
{
17821791
/* Failed to find a free slot within specified range */
17831792
if (use_lock)
17841793
LWLockRelease(ControlFileLock);
17851794
return false;
17861795
}
1787-
NextLogSeg(log, seg);
1788-
XLogFilePath(path, ThisTimeLineID, log, seg);
1796+
NextLogSeg(*log, *seg);
1797+
(*max_advance)--;
1798+
XLogFilePath(path, ThisTimeLineID, *log, *seg);
17891799
}
17901800
}
17911801

@@ -1799,14 +1809,14 @@ InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath,
17991809
ereport(PANIC,
18001810
(errcode_for_file_access(),
18011811
errmsg("could not link file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
1802-
tmppath, path, log, seg)));
1812+
tmppath, path, *log, *seg)));
18031813
unlink(tmppath);
18041814
#else
18051815
if (rename(tmppath, path) < 0)
18061816
ereport(PANIC,
18071817
(errcode_for_file_access(),
18081818
errmsg("could not rename file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
1809-
tmppath, path, log, seg)));
1819+
tmppath, path, *log, *seg)));
18101820
#endif
18111821

18121822
if (use_lock)
@@ -2129,6 +2139,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
21292139
{
21302140
uint32 endlogId;
21312141
uint32 endlogSeg;
2142+
int max_advance;
21322143
DIR *xldir;
21332144
struct dirent *xlde;
21342145
char lastoff[MAXFNAMELEN];
@@ -2137,7 +2148,12 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
21372148
*nsegsremoved = 0;
21382149
*nsegsrecycled = 0;
21392150

2151+
/*
2152+
* Initialize info about where to try to recycle to. We allow recycling
2153+
* segments up to XLOGfileslop segments beyond the current XLOG location.
2154+
*/
21402155
XLByteToPrevSeg(endptr, endlogId, endlogSeg);
2156+
max_advance = XLOGfileslop;
21412157

21422158
xldir = AllocateDir(XLogDir);
21432159
if (xldir == NULL)
@@ -2179,12 +2195,10 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
21792195

21802196
/*
21812197
* Before deleting the file, see if it can be recycled as
2182-
* a future log segment. We allow recycling segments up
2183-
* to XLOGfileslop segments beyond the current XLOG
2184-
* location.
2198+
* a future log segment.
21852199
*/
2186-
if (InstallXLogFileSegment(endlogId, endlogSeg, path,
2187-
true, XLOGfileslop,
2200+
if (InstallXLogFileSegment(&endlogId, &endlogSeg, path,
2201+
true, &max_advance,
21882202
true))
21892203
{
21902204
ereport(DEBUG2,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy