@@ -462,6 +462,11 @@ typedef struct XLogCtlData
462
462
463
463
/* Fake LSN counter, for unlogged relations. */
464
464
pg_atomic_uint64 unloggedLSN ;
465
+ /*
466
+ * Approximation of the last WAL segment number that is known to have been
467
+ * installed by InstallXLogFileSegment().
468
+ */
469
+ pg_atomic_uint64 last_known_installed_segno ;
465
470
466
471
/* Time and LSN of last xlog segment switch. Protected by WALWriteLock. */
467
472
pg_time_t lastSegSwitchTime ;
@@ -3224,7 +3229,28 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli,
3224
3229
errmsg ("could not open file \"%s\": %m" , path )));
3225
3230
}
3226
3231
else
3232
+ {
3233
+ /*
3234
+ * The file is there, but it is possible that InstallXLogFileSegment()
3235
+ * has recently renamed it and not yet made the new name durable. We
3236
+ * don't want to be able to flush data into a file whose name might
3237
+ * not survive power loss, since it would become unreachable in
3238
+ * recovery. Since InstallXlogFileSegment() holds ControlFileLock,
3239
+ * acquiring it here is enough to wait for any durable_rename() call
3240
+ * that might have started before we opened the file.
3241
+ *
3242
+ * We can skip that if we can already see that the WAL space we need
3243
+ * is fully synchronized. We may see a slightly out of date value
3244
+ * since we haven't acquired the lock yet, but that's OK, it just
3245
+ * means we might take the lock when we don't need to.
3246
+ */
3247
+ if (pg_atomic_read_u64 (& XLogCtl -> last_known_installed_segno ) < logsegno )
3248
+ {
3249
+ LWLockAcquire (ControlFileLock , LW_SHARED );
3250
+ LWLockRelease (ControlFileLock );
3251
+ }
3227
3252
return fd ;
3253
+ }
3228
3254
3229
3255
/*
3230
3256
* Initialize an empty (all zeroes) segment. NOTE: it is possible that
@@ -3576,6 +3602,11 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3576
3602
3577
3603
XLogFilePath (path , tli , * segno , wal_segment_size );
3578
3604
3605
+ /*
3606
+ * Acquire and keep the ControlFileLock held *until* we have renamed the
3607
+ * target segment durably. See XLogFileInitInternal() for details as to why
3608
+ * it is dangerous otherwise.
3609
+ */
3579
3610
LWLockAcquire (ControlFileLock , LW_EXCLUSIVE );
3580
3611
if (!XLogCtl -> InstallXLogFileSegmentActive )
3581
3612
{
@@ -3612,6 +3643,8 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
3612
3643
return false;
3613
3644
}
3614
3645
3646
+ pg_atomic_write_u64 (& XLogCtl -> last_known_installed_segno , * segno );
3647
+
3615
3648
LWLockRelease (ControlFileLock );
3616
3649
3617
3650
return true;
@@ -4970,6 +5003,7 @@ XLOGShmemInit(void)
4970
5003
char * allocptr ;
4971
5004
int i ;
4972
5005
ControlFileData * localControlFile ;
5006
+ XLogSegNo lastKnownInstalledSegno = 0 ;
4973
5007
4974
5008
#ifdef WAL_DEBUG
4975
5009
@@ -5017,6 +5051,12 @@ XLOGShmemInit(void)
5017
5051
{
5018
5052
memcpy (ControlFile , localControlFile , sizeof (ControlFileData ));
5019
5053
pfree (localControlFile );
5054
+ /*
5055
+ * A decent approximation for the last known installed WAL segment
5056
+ * number can be the segment in which the checkpoint record resides,
5057
+ * specially in cases where we have had a clean shutdown.
5058
+ */
5059
+ XLByteToSeg (ControlFile -> checkPoint , lastKnownInstalledSegno , wal_segment_size );
5020
5060
}
5021
5061
5022
5062
/*
@@ -5071,6 +5111,7 @@ XLOGShmemInit(void)
5071
5111
pg_atomic_init_u64 (& XLogCtl -> logWriteResult , InvalidXLogRecPtr );
5072
5112
pg_atomic_init_u64 (& XLogCtl -> logFlushResult , InvalidXLogRecPtr );
5073
5113
pg_atomic_init_u64 (& XLogCtl -> unloggedLSN , InvalidXLogRecPtr );
5114
+ pg_atomic_init_u64 (& XLogCtl -> last_known_installed_segno , lastKnownInstalledSegno );
5074
5115
}
5075
5116
5076
5117
/*
0 commit comments