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

Commit5a38af7

Browse files
committed
Rearrange XLogFileInit so that control-file spinlock is not held while filling
the new log file with zeroes, only while renaming it into place. This shouldprevent problems with 'stuck spinlock' errors under heavy load.
1 parent5dc0e67 commit5a38af7

File tree

1 file changed

+117
-75
lines changed
  • src/backend/access/transam

1 file changed

+117
-75
lines changed

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

Lines changed: 117 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.59 2001/03/16 05:44:33 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.60 2001/03/17 20:54:13 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -86,7 +86,7 @@
8686
/* Max time to wait to acquire XLog activity locks */
8787
#defineXLOG_LOCK_TIMEOUT(5*60*1000000)/* 5 minutes */
8888
/* Max time to wait to acquire checkpoint lock */
89-
#defineCHECKPOINT_LOCK_TIMEOUT(10*60*1000000)/*10 minutes */
89+
#defineCHECKPOINT_LOCK_TIMEOUT(20*60*1000000)/*20 minutes */
9090

9191
/* User-settable parameters */
9292
intCheckPointSegments=3;
@@ -335,10 +335,6 @@ static ControlFileData *ControlFile = NULL;
335335
snprintf(path, MAXPGPATH, "%s%c%08X%08X",\
336336
XLogDir, SEP_CHAR, log, seg)
337337

338-
#defineXLogTempFileName(path,log,seg)\
339-
snprintf(path, MAXPGPATH, "%s%cT%08X%08X",\
340-
XLogDir, SEP_CHAR, log, seg)
341-
342338
#definePrevBufIdx(idx)\
343339
(((idx) == 0) ? XLogCtl->XLogCacheBlck : ((idx) - 1))
344340

@@ -401,7 +397,8 @@ static bool InRedo = false;
401397

402398
staticboolAdvanceXLInsertBuffer(void);
403399
staticvoidXLogWrite(XLogwrtRqstWriteRqst);
404-
staticintXLogFileInit(uint32log,uint32seg,bool*usexistent);
400+
staticintXLogFileInit(uint32log,uint32seg,
401+
bool*use_existent,booluse_lock);
405402
staticintXLogFileOpen(uint32log,uint32seg,boolecont);
406403
staticvoidPreallocXlogFiles(XLogRecPtrendptr);
407404
staticvoidMoveOfflineLogs(uint32log,uint32seg);
@@ -960,7 +957,7 @@ XLogWrite(XLogwrtRqst WriteRqst)
960957
XLogCtlWrite*Write=&XLogCtl->Write;
961958
char*from;
962959
boolispartialpage;
963-
boolusexistent;
960+
booluse_existent;
964961

965962
/* Update local LogwrtResult (caller probably did this already, but...) */
966963
LogwrtResult=Write->LogwrtResult;
@@ -994,41 +991,42 @@ XLogWrite(XLogwrtRqst WriteRqst)
994991
}
995992
XLByteToPrevSeg(LogwrtResult.Write,openLogId,openLogSeg);
996993

997-
/* create/use new log file; need lock in case creating */
998-
SpinAcquire(ControlFileLockId);
999-
usexistent=true;
1000-
openLogFile=XLogFileInit(openLogId,openLogSeg,&usexistent);
994+
/* create/use new log file */
995+
use_existent= true;
996+
openLogFile=XLogFileInit(openLogId,openLogSeg,
997+
&use_existent, true);
1001998
openLogOff=0;
999+
1000+
if (!use_existent)/* there was no precreated file */
1001+
elog(LOG,"XLogWrite: new log file created - "
1002+
"consider increasing WAL_FILES");
1003+
10021004
/* update pg_control, unless someone else already did */
1005+
SpinAcquire(ControlFileLockId);
10031006
if (ControlFile->logId!=openLogId||
10041007
ControlFile->logSeg!=openLogSeg+1)
10051008
{
10061009
ControlFile->logId=openLogId;
10071010
ControlFile->logSeg=openLogSeg+1;
10081011
ControlFile->time=time(NULL);
10091012
UpdateControlFile();
1013+
/*
1014+
* Signal postmaster to start a checkpoint if it's been too
1015+
* long since the last one. (We look at local copy of
1016+
* RedoRecPtr which might be a little out of date, but should
1017+
* be close enough for this purpose.)
1018+
*/
1019+
if (IsUnderPostmaster&&
1020+
(openLogId!=RedoRecPtr.xlogid||
1021+
openLogSeg >= (RedoRecPtr.xrecoff /XLogSegSize)+
1022+
(uint32)CheckPointSegments))
1023+
{
1024+
if (XLOG_DEBUG)
1025+
fprintf(stderr,"XLogWrite: time for a checkpoint, signaling postmaster\n");
1026+
kill(getppid(),SIGUSR1);
1027+
}
10101028
}
10111029
SpinRelease(ControlFileLockId);
1012-
1013-
if (!usexistent)/* there was no precreated file */
1014-
elog(LOG,"XLogWrite: new log file created - "
1015-
"consider increasing WAL_FILES");
1016-
1017-
/*
1018-
* Signal postmaster to start a checkpoint if it's been too
1019-
* long since the last one. (We look at local copy of RedoRecPtr
1020-
* which might be a little out of date, but should be close enough
1021-
* for this purpose.)
1022-
*/
1023-
if (IsUnderPostmaster&&
1024-
(openLogId!=RedoRecPtr.xlogid||
1025-
openLogSeg >= (RedoRecPtr.xrecoff /XLogSegSize)+
1026-
(uint32)CheckPointSegments))
1027-
{
1028-
if (XLOG_DEBUG)
1029-
fprintf(stderr,"XLogWrite: time for a checkpoint, signaling postmaster\n");
1030-
kill(getppid(),SIGUSR1);
1031-
}
10321030
}
10331031

10341032
if (openLogFile<0)
@@ -1230,14 +1228,28 @@ XLogFlush(XLogRecPtr record)
12301228
/*
12311229
* Create a new XLOG file segment, or open a pre-existing one.
12321230
*
1231+
* log, seg: identify segment to be created/opened.
1232+
*
1233+
* *use_existent: if TRUE, OK to use a pre-existing file (else, any
1234+
* pre-existing file will be deleted). On return, TRUE if a pre-existing
1235+
* file was used.
1236+
*
1237+
* use_lock: if TRUE, acquire ControlFileLock spinlock while moving file into
1238+
* place. This should be TRUE except during bootstrap log creation. The
1239+
* caller must *not* hold the spinlock at call.
1240+
*
12331241
* Returns FD of opened file.
12341242
*/
12351243
staticint
1236-
XLogFileInit(uint32log,uint32seg,bool*usexistent)
1244+
XLogFileInit(uint32log,uint32seg,
1245+
bool*use_existent,booluse_lock)
12371246
{
12381247
charpath[MAXPGPATH];
1239-
chartpath[MAXPGPATH];
1248+
chartmppath[MAXPGPATH];
1249+
chartargpath[MAXPGPATH];
12401250
charzbuffer[BLCKSZ];
1251+
uint32targlog,
1252+
targseg;
12411253
intfd;
12421254
intnbytes;
12431255

@@ -1246,7 +1258,7 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
12461258
/*
12471259
* Try to use existent file (checkpoint maker may have created it already)
12481260
*/
1249-
if (*usexistent)
1261+
if (*use_existent)
12501262
{
12511263
fd=BasicOpenFile(path,O_RDWR |PG_BINARY |XLOG_SYNC_BIT,
12521264
S_IRUSR |S_IWUSR);
@@ -1258,20 +1270,24 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
12581270
}
12591271
else
12601272
return(fd);
1261-
/* Set flag to tell caller there was no existent file */
1262-
*usexistent= false;
12631273
}
12641274

1265-
XLogTempFileName(tpath,log,seg);
1266-
unlink(tpath);
1267-
unlink(path);
1275+
/*
1276+
* Initialize an empty (all zeroes) segment. NOTE: it is possible that
1277+
* another process is doing the same thing. If so, we will end up
1278+
* pre-creating an extra log segment. That seems OK, and better than
1279+
* holding the spinlock throughout this lengthy process.
1280+
*/
1281+
snprintf(tmppath,MAXPGPATH,"%s%cxlogtemp.%d",
1282+
XLogDir,SEP_CHAR, (int)getpid());
1283+
1284+
unlink(tmppath);
12681285

12691286
/* do not use XLOG_SYNC_BIT here --- want to fsync only at end of fill */
1270-
fd=BasicOpenFile(tpath,O_RDWR |O_CREAT |O_EXCL |PG_BINARY,
1287+
fd=BasicOpenFile(tmppath,O_RDWR |O_CREAT |O_EXCL |PG_BINARY,
12711288
S_IRUSR |S_IWUSR);
12721289
if (fd<0)
1273-
elog(STOP,"InitCreate(logfile %u seg %u) failed: %m",
1274-
log,seg);
1290+
elog(STOP,"InitCreate(%s) failed: %m",tmppath);
12751291

12761292
/*
12771293
* Zero-fill the file. We have to do this the hard way to ensure that
@@ -1290,36 +1306,73 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
12901306
intsave_errno=errno;
12911307

12921308
/* If we fail to make the file, delete it to release disk space */
1293-
unlink(tpath);
1309+
unlink(tmppath);
12941310
errno=save_errno;
12951311

1296-
elog(STOP,"ZeroFill(logfile %u seg %u) failed: %m",
1297-
log,seg);
1312+
elog(STOP,"ZeroFill(%s) failed: %m",tmppath);
12981313
}
12991314
}
13001315

13011316
if (pg_fsync(fd)!=0)
1302-
elog(STOP,"fsync(logfile %u seg %u) failed: %m",
1303-
log,seg);
1317+
elog(STOP,"fsync(%s) failed: %m",tmppath);
13041318

13051319
close(fd);
13061320

13071321
/*
1308-
* Prefer link() to rename() here just to be sure that we don't overwrite
1309-
* an existing logfile. However, there shouldn't be one, so rename()
1310-
* is an acceptable substitute except for the truly paranoid.
1322+
* Now move the segment into place with its final name. We want to be
1323+
* sure that only one process does this at a time.
1324+
*/
1325+
if (use_lock)
1326+
SpinAcquire(ControlFileLockId);
1327+
1328+
/*
1329+
* If caller didn't want to use a pre-existing file, get rid of any
1330+
* pre-existing file. Otherwise, cope with possibility that someone
1331+
* else has created the file while we were filling ours: if so, use
1332+
* ours to pre-create a future log segment.
1333+
*/
1334+
targlog=log;
1335+
targseg=seg;
1336+
strcpy(targpath,path);
1337+
1338+
if (!*use_existent)
1339+
{
1340+
unlink(targpath);
1341+
}
1342+
else
1343+
{
1344+
while ((fd=BasicOpenFile(targpath,O_RDWR |PG_BINARY,
1345+
S_IRUSR |S_IWUSR)) >=0)
1346+
{
1347+
close(fd);
1348+
NextLogSeg(targlog,targseg);
1349+
XLogFileName(targpath,targlog,targseg);
1350+
}
1351+
}
1352+
1353+
/*
1354+
* Prefer link() to rename() here just to be really sure that we don't
1355+
* overwrite an existing logfile. However, there shouldn't be one, so
1356+
* rename() is an acceptable substitute except for the truly paranoid.
13111357
*/
13121358
#ifndef__BEOS__
1313-
if (link(tpath,path)<0)
1359+
if (link(tmppath,targpath)<0)
13141360
elog(STOP,"InitRelink(logfile %u seg %u) failed: %m",
1315-
log,seg);
1316-
unlink(tpath);
1361+
targlog,targseg);
1362+
unlink(tmppath);
13171363
#else
1318-
if (rename(tpath,path)<0)
1364+
if (rename(tmppath,targpath)<0)
13191365
elog(STOP,"InitRelink(logfile %u seg %u) failed: %m",
1320-
log,seg);
1366+
targlog,targseg);
13211367
#endif
13221368

1369+
if (use_lock)
1370+
SpinRelease(ControlFileLockId);
1371+
1372+
/* Set flag to tell caller there was no existent file */
1373+
*use_existent= false;
1374+
1375+
/* Now open original target segment (might not be file I just made) */
13231376
fd=BasicOpenFile(path,O_RDWR |PG_BINARY |XLOG_SYNC_BIT,
13241377
S_IRUSR |S_IWUSR);
13251378
if (fd<0)
@@ -1367,39 +1420,27 @@ PreallocXlogFiles(XLogRecPtr endptr)
13671420
uint32_logId;
13681421
uint32_logSeg;
13691422
intlf;
1370-
boolusexistent;
1371-
structtimevaldelay;
1423+
booluse_existent;
13721424
inti;
13731425

13741426
XLByteToPrevSeg(endptr,_logId,_logSeg);
13751427
if (XLOGfiles>0)
13761428
{
13771429
for (i=1;i <=XLOGfiles;i++)
13781430
{
1379-
usexistent= true;
13801431
NextLogSeg(_logId,_logSeg);
1381-
SpinAcquire(ControlFileLockId);
1382-
lf=XLogFileInit(_logId,_logSeg,&usexistent);
1432+
use_existent= true;
1433+
lf=XLogFileInit(_logId,_logSeg,&use_existent, true);
13831434
close(lf);
1384-
SpinRelease(ControlFileLockId);
1385-
/*
1386-
* Give up ControlFileLockId for 1/50 sec to let other
1387-
* backends switch to new log file in XLogWrite()
1388-
*/
1389-
delay.tv_sec=0;
1390-
delay.tv_usec=20000;
1391-
(void)select(0,NULL,NULL,NULL,&delay);
13921435
}
13931436
}
13941437
elseif ((endptr.xrecoff-1) %XLogSegSize >=
13951438
(uint32) (0.75*XLogSegSize))
13961439
{
1397-
usexistent= true;
13981440
NextLogSeg(_logId,_logSeg);
1399-
SpinAcquire(ControlFileLockId);
1400-
lf=XLogFileInit(_logId,_logSeg,&usexistent);
1441+
use_existent= true;
1442+
lf=XLogFileInit(_logId,_logSeg,&use_existent, true);
14011443
close(lf);
1402-
SpinRelease(ControlFileLockId);
14031444
}
14041445
}
14051446

@@ -2103,7 +2144,7 @@ BootStrapXLOG(void)
21032144
char*buffer;
21042145
XLogPageHeaderpage;
21052146
XLogRecord*record;
2106-
boolusexistent= false;
2147+
booluse_existent;
21072148
crc64crc;
21082149

21092150
/* Use malloc() to ensure buffer is MAXALIGNED */
@@ -2144,7 +2185,8 @@ BootStrapXLOG(void)
21442185
FIN_CRC64(crc);
21452186
record->xl_crc=crc;
21462187

2147-
openLogFile=XLogFileInit(0,0,&usexistent);
2188+
use_existent= false;
2189+
openLogFile=XLogFileInit(0,0,&use_existent, false);
21482190

21492191
if (write(openLogFile,buffer,BLCKSZ)!=BLCKSZ)
21502192
elog(STOP,"BootStrapXLOG failed to write logfile: %m");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp