Skip to content

Commit acd4c7d

Browse files
committed
Fix an issue in recent walwriter hibernation patch.
Users of asynchronous-commit mode expect there to be a guaranteed maximum delay before an async commit's WAL records get flushed to disk. The original version of the walwriter hibernation patch broke that. Add an extra shared-memory flag to allow async commits to kick the walwriter out of hibernation mode, without adding any noticeable overhead in cases where no action is needed.
1 parent 8b77e22 commit acd4c7d

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

src/backend/access/transam/xlog.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ typedef struct XLogCtlData
426426
*/
427427
bool SharedHotStandbyActive;
428428

429+
/*
430+
* WalWriterSleeping indicates whether the WAL writer is currently in
431+
* low-power mode (and hence should be nudged if an async commit occurs).
432+
* Protected by info_lck.
433+
*/
434+
bool WalWriterSleeping;
435+
429436
/*
430437
* recoveryWakeupLatch is used to wake up the startup process to continue
431438
* WAL replay, if it is waiting for WAL to arrive or failover trigger file
@@ -1903,32 +1910,44 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
19031910

19041911
/*
19051912
* Record the LSN for an asynchronous transaction commit/abort
1906-
* and nudge the WALWriter if there is a complete page to write.
1913+
* and nudge the WALWriter if there is work for it to do.
19071914
* (This should not be called for synchronous commits.)
19081915
*/
19091916
void
19101917
XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
19111918
{
19121919
XLogRecPtr WriteRqstPtr = asyncXactLSN;
1920+
bool sleeping;
19131921

19141922
/* use volatile pointer to prevent code rearrangement */
19151923
volatile XLogCtlData *xlogctl = XLogCtl;
19161924

19171925
SpinLockAcquire(&xlogctl->info_lck);
19181926
LogwrtResult = xlogctl->LogwrtResult;
1927+
sleeping = xlogctl->WalWriterSleeping;
19191928
if (XLByteLT(xlogctl->asyncXactLSN, asyncXactLSN))
19201929
xlogctl->asyncXactLSN = asyncXactLSN;
19211930
SpinLockRelease(&xlogctl->info_lck);
19221931

1923-
/* back off to last completed page boundary */
1924-
WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
1932+
/*
1933+
* If the WALWriter is sleeping, we should kick it to make it come out of
1934+
* low-power mode. Otherwise, determine whether there's a full page of
1935+
* WAL available to write.
1936+
*/
1937+
if (!sleeping)
1938+
{
1939+
/* back off to last completed page boundary */
1940+
WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ;
19251941

1926-
/* if we have already flushed that far, we're done */
1927-
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
1928-
return;
1942+
/* if we have already flushed that far, we're done */
1943+
if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
1944+
return;
1945+
}
19291946

19301947
/*
1931-
* Nudge the WALWriter if we have a full page of WAL to write.
1948+
* Nudge the WALWriter: it has a full page of WAL to write, or we want
1949+
* it to come out of low-power mode so that this async commit will reach
1950+
* disk within the expected amount of time.
19321951
*/
19331952
if (ProcGlobal->walwriterLatch)
19341953
SetLatch(ProcGlobal->walwriterLatch);
@@ -5100,6 +5119,7 @@ XLOGShmemInit(void)
51005119
XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
51015120
XLogCtl->SharedRecoveryInProgress = true;
51025121
XLogCtl->SharedHotStandbyActive = false;
5122+
XLogCtl->WalWriterSleeping = false;
51035123
XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
51045124
SpinLockInit(&XLogCtl->info_lck);
51055125
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
@@ -10479,3 +10499,17 @@ WakeupRecovery(void)
1047910499
{
1048010500
SetLatch(&XLogCtl->recoveryWakeupLatch);
1048110501
}
10502+
10503+
/*
10504+
* Update the WalWriterSleeping flag.
10505+
*/
10506+
void
10507+
SetWalWriterSleeping(bool sleeping)
10508+
{
10509+
/* use volatile pointer to prevent code rearrangement */
10510+
volatile XLogCtlData *xlogctl = XLogCtl;
10511+
10512+
SpinLockAcquire(&xlogctl->info_lck);
10513+
xlogctl->WalWriterSleeping = sleeping;
10514+
SpinLockRelease(&xlogctl->info_lck);
10515+
}

src/backend/postmaster/walwriter.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ WalWriterMain(void)
9999
sigjmp_buf local_sigjmp_buf;
100100
MemoryContext walwriter_context;
101101
int left_till_hibernate;
102+
bool hibernating;
102103

103104
/*
104105
* If possible, make this process a group leader, so that the postmaster
@@ -230,6 +231,8 @@ WalWriterMain(void)
230231
* Reset hibernation state after any error.
231232
*/
232233
left_till_hibernate = LOOPS_UNTIL_HIBERNATE;
234+
hibernating = false;
235+
SetWalWriterSleeping(false);
233236

234237
/*
235238
* Advertise our latch that backends can use to wake us up while we're
@@ -244,6 +247,21 @@ WalWriterMain(void)
244247
{
245248
long cur_timeout;
246249

250+
/*
251+
* Advertise whether we might hibernate in this cycle. We do this
252+
* before resetting the latch to ensure that any async commits will
253+
* see the flag set if they might possibly need to wake us up, and
254+
* that we won't miss any signal they send us. (If we discover work
255+
* to do in the last cycle before we would hibernate, the global flag
256+
* will be set unnecessarily, but little harm is done.) But avoid
257+
* touching the global flag if it doesn't need to change.
258+
*/
259+
if (hibernating != (left_till_hibernate <= 1))
260+
{
261+
hibernating = (left_till_hibernate <= 1);
262+
SetWalWriterSleeping(hibernating);
263+
}
264+
247265
/* Clear any already-pending wakeups */
248266
ResetLatch(&MyProc->procLatch);
249267

src/include/access/xlog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ extern TimeLineID GetRecoveryTargetTLI(void);
316316

317317
extern bool CheckPromoteSignal(void);
318318
extern void WakeupRecovery(void);
319+
extern void SetWalWriterSleeping(bool sleeping);
319320

320321
/*
321322
* Starting/stopping a base backup

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