@@ -426,6 +426,13 @@ typedef struct XLogCtlData
426
426
*/
427
427
bool SharedHotStandbyActive ;
428
428
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
+
429
436
/*
430
437
* recoveryWakeupLatch is used to wake up the startup process to continue
431
438
* 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)
1903
1910
1904
1911
/*
1905
1912
* 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 .
1907
1914
* (This should not be called for synchronous commits.)
1908
1915
*/
1909
1916
void
1910
1917
XLogSetAsyncXactLSN (XLogRecPtr asyncXactLSN )
1911
1918
{
1912
1919
XLogRecPtr WriteRqstPtr = asyncXactLSN ;
1920
+ bool sleeping ;
1913
1921
1914
1922
/* use volatile pointer to prevent code rearrangement */
1915
1923
volatile XLogCtlData * xlogctl = XLogCtl ;
1916
1924
1917
1925
SpinLockAcquire (& xlogctl -> info_lck );
1918
1926
LogwrtResult = xlogctl -> LogwrtResult ;
1927
+ sleeping = xlogctl -> WalWriterSleeping ;
1919
1928
if (XLByteLT (xlogctl -> asyncXactLSN , asyncXactLSN ))
1920
1929
xlogctl -> asyncXactLSN = asyncXactLSN ;
1921
1930
SpinLockRelease (& xlogctl -> info_lck );
1922
1931
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 ;
1925
1941
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
+ }
1929
1946
1930
1947
/*
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.
1932
1951
*/
1933
1952
if (ProcGlobal -> walwriterLatch )
1934
1953
SetLatch (ProcGlobal -> walwriterLatch );
@@ -5100,6 +5119,7 @@ XLOGShmemInit(void)
5100
5119
XLogCtl -> XLogCacheBlck = XLOGbuffers - 1 ;
5101
5120
XLogCtl -> SharedRecoveryInProgress = true;
5102
5121
XLogCtl -> SharedHotStandbyActive = false;
5122
+ XLogCtl -> WalWriterSleeping = false;
5103
5123
XLogCtl -> Insert .currpage = (XLogPageHeader ) (XLogCtl -> pages );
5104
5124
SpinLockInit (& XLogCtl -> info_lck );
5105
5125
InitSharedLatch (& XLogCtl -> recoveryWakeupLatch );
@@ -10479,3 +10499,17 @@ WakeupRecovery(void)
10479
10499
{
10480
10500
SetLatch (& XLogCtl -> recoveryWakeupLatch );
10481
10501
}
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
+ }
0 commit comments