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

Commit7f2a10f

Browse files
committed
Don't error out if recycling or removing an old WAL segment fails at the end
of checkpoint. Although the checkpoint has been written to WAL at that pointalready, so that all data is safe, and we'll retry removing the WAL segment atthe next checkpoint, if such a failure persists we won't be able to remove anyother old WAL segments either and will eventually run out of disk space. It'sbetter to treat the failure as non-fatal, and move on to clean any other WALsegment and continue with any other end-of-checkpoint cleanup.We don't normally expect any such failures, but on Windows it can happen withsome anti-virus or backup software that lock files without FILE_SHARE_DELETEflag.Also, the loop in pgrename() to retry when the file is locked was broken. If afile is locked on Windows, you get ERROR_SHARE_VIOLATION, notERROR_ACCESS_DENIED, at least on modern versions. Fix that, although I leftthe check for ERROR_ACCESS_DENIED in there as well (presumably it was correctin some environment), and added ERROR_LOCK_VIOLATION to be consistent withsimilar checks in pgwin32_open(). Reduce the timeout on the loop from 30s to10s, on the grounds that since it's been broken, we've effectively had atimeout of 0s and no-one has complained, so a smaller timeout is actuallycloser to the old behavior. A longer timeout would mean that if recycling aWAL file fails because it's locked for some reason, InstallXLogFileSegment()will hold ControlFileLock for longer, potentially blocking other backends, soa long timeout isn't totally harmless.While we're at it, set errno correctly in pgrename().Backpatch to 8.2, which is the oldest version supported on Windows. The xlog.cchanges would make sense on other platforms and thus on older versions aswell, but since there's no such locking issues on other platforms, it's notworth it.
1 parentd6119d8 commit7f2a10f

File tree

2 files changed

+55
-35
lines changed

2 files changed

+55
-35
lines changed

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

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2009, 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.352 2009/09/10 09:42:10 heikki Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.353 2009/09/13 18:32:07 heikki Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -2262,12 +2262,14 @@ XLogFileInit(uint32 log, uint32 seg,
22622262
*use_existent,&max_advance,
22632263
use_lock))
22642264
{
2265-
/* No need for any more future segments... */
2265+
/*
2266+
* No need for any more future segments, or InstallXLogFileSegment()
2267+
* failed to rename the file into place. If the rename failed, opening
2268+
* the file below will fail.
2269+
*/
22662270
unlink(tmppath);
22672271
}
22682272

2269-
elog(DEBUG2,"done creating and filling new WAL file");
2270-
22712273
/* Set flag to tell caller there was no existent file */
22722274
*use_existent= false;
22732275

@@ -2280,6 +2282,8 @@ XLogFileInit(uint32 log, uint32 seg,
22802282
errmsg("could not open file \"%s\" (log file %u, segment %u): %m",
22812283
path,log,seg)));
22822284

2285+
elog(DEBUG2,"done creating and filling new WAL file");
2286+
22832287
returnfd;
22842288
}
22852289

@@ -2409,10 +2413,9 @@ XLogFileCopy(uint32 log, uint32 seg,
24092413
* place. This should be TRUE except during bootstrap log creation. The
24102414
* caller must *not* hold the lock at call.
24112415
*
2412-
* Returns TRUE if file installed, FALSE if not installed because of
2413-
* exceeding max_advance limit. On Windows, we also return FALSE if we
2414-
* can't rename the file into place because someone's got it open.
2415-
* (Any other kind of failure causes ereport().)
2416+
* Returns TRUE if the file was installed successfully. FALSE indicates that
2417+
* max_advance limit was exceeded, or an error occurred while renaming the
2418+
* file into place.
24162419
*/
24172420
staticbool
24182421
InstallXLogFileSegment(uint32*log,uint32*seg,char*tmppath,
@@ -2460,31 +2463,26 @@ InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
24602463
*/
24612464
#ifHAVE_WORKING_LINK
24622465
if (link(tmppath,path)<0)
2463-
ereport(ERROR,
2466+
{
2467+
if (use_lock)
2468+
LWLockRelease(ControlFileLock);
2469+
ereport(LOG,
24642470
(errcode_for_file_access(),
24652471
errmsg("could not link file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
24662472
tmppath,path,*log,*seg)));
2473+
return false;
2474+
}
24672475
unlink(tmppath);
24682476
#else
24692477
if (rename(tmppath,path)<0)
24702478
{
2471-
#ifdefWIN32
2472-
#if !defined(__CYGWIN__)
2473-
if (GetLastError()==ERROR_ACCESS_DENIED)
2474-
#else
2475-
if (errno==EACCES)
2476-
#endif
2477-
{
2478-
if (use_lock)
2479-
LWLockRelease(ControlFileLock);
2480-
return false;
2481-
}
2482-
#endif/* WIN32 */
2483-
2484-
ereport(ERROR,
2479+
if (use_lock)
2480+
LWLockRelease(ControlFileLock);
2481+
ereport(LOG,
24852482
(errcode_for_file_access(),
24862483
errmsg("could not rename file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
24872484
tmppath,path,*log,*seg)));
2485+
return false;
24882486
}
24892487
#endif
24902488

@@ -3128,19 +3126,25 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
31283126
*/
31293127
snprintf(newpath,MAXPGPATH,"%s.deleted",path);
31303128
if (rename(path,newpath)!=0)
3131-
ereport(ERROR,
3129+
{
3130+
ereport(LOG,
31323131
(errcode_for_file_access(),
3133-
errmsg("could not rename old transaction log file \"%s\"",
3132+
errmsg("could not rename old transaction log file \"%s\": %m",
31343133
path)));
3134+
continue;
3135+
}
31353136
rc=unlink(newpath);
31363137
#else
31373138
rc=unlink(path);
31383139
#endif
31393140
if (rc!=0)
3140-
ereport(ERROR,
3141+
{
3142+
ereport(LOG,
31413143
(errcode_for_file_access(),
31423144
errmsg("could not remove old transaction log file \"%s\": %m",
31433145
path)));
3146+
continue;
3147+
}
31443148
CheckpointStats.ckpt_segs_removed++;
31453149
}
31463150

‎src/port/dirmod.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*Win32 (NT4 and newer).
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.58 2009/06/11 14:49:15 momjian Exp $
13+
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.59 2009/09/13 18:32:08 heikki Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -120,7 +120,8 @@ pgrename(const char *from, const char *to)
120120
* We need to loop because even though PostgreSQL uses flags that allow
121121
* rename while the file is open, other applications might have the file
122122
* open without those flags. However, we won't wait indefinitely for
123-
* someone else to close the file.
123+
* someone else to close the file, as the caller might be holding locks
124+
* and blocking other backends.
124125
*/
125126
#if defined(WIN32)&& !defined(__CYGWIN__)
126127
while (!MoveFileEx(from,to,MOVEFILE_REPLACE_EXISTING))
@@ -129,13 +130,28 @@ pgrename(const char *from, const char *to)
129130
#endif
130131
{
131132
#if defined(WIN32)&& !defined(__CYGWIN__)
132-
if (GetLastError()!=ERROR_ACCESS_DENIED)
133+
DWORDerr=GetLastError();
134+
135+
_dosmaperr(err);
136+
137+
/*
138+
* Modern NT-based Windows versions return ERROR_SHARING_VIOLATION
139+
* if another process has the file open without FILE_SHARE_DELETE.
140+
* ERROR_LOCK_VIOLATION has also been seen with some anti-virus
141+
* software. This used to check for just ERROR_ACCESS_DENIED, so
142+
* presumably you can get that too with some OS versions. We don't
143+
* expect real permission errors where we currently use rename().
144+
*/
145+
if (err!=ERROR_ACCESS_DENIED&&
146+
err!=ERROR_SHARING_VIOLATION&&
147+
err!=ERROR_LOCK_VIOLATION)
148+
return-1;
133149
#else
134150
if (errno!=EACCES)
135-
#endif
136-
/* set errno? */
137151
return-1;
138-
if (++loops>300)/* time out after 30 sec */
152+
#endif
153+
154+
if (++loops>100)/* time out after 10 sec */
139155
return-1;
140156
pg_usleep(100000);/* us */
141157
}
@@ -155,14 +171,14 @@ pgunlink(const char *path)
155171
* We need to loop because even though PostgreSQL uses flags that allow
156172
* unlink while the file is open, other applications might have the file
157173
* open without those flags. However, we won't wait indefinitely for
158-
* someone else to close the file.
174+
* someone else to close the file, as the caller might be holding locks
175+
* and blocking other backends.
159176
*/
160177
while (unlink(path))
161178
{
162179
if (errno!=EACCES)
163-
/* set errno? */
164180
return-1;
165-
if (++loops>300)/* time out after30 sec */
181+
if (++loops>100)/* time out after10 sec */
166182
return-1;
167183
pg_usleep(100000);/* us */
168184
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp