diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 0d494e2e3b..20c04240b7 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -432,6 +432,11 @@ typedef struct XLogCtlData */ Latch recoveryWakeupLatch; + /* + * WALWriterLatch is used to wake up the WALWriter to write some WAL. + */ + Latch WALWriterLatch; + /* * During recovery, we keep a copy of the latest checkpoint record here. * Used by the background writer when it wants to create a restartpoint. @@ -1916,19 +1921,35 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch) } /* - * Record the LSN for an asynchronous transaction commit/abort. + * Record the LSN for an asynchronous transaction commit/abort + * and nudge the WALWriter if there is a complete page to write. * (This should not be called for for synchronous commits.) */ void XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN) { + XLogRecPtr WriteRqstPtr = asyncXactLSN; + /* use volatile pointer to prevent code rearrangement */ volatile XLogCtlData *xlogctl = XLogCtl; SpinLockAcquire(&xlogctl->info_lck); + LogwrtResult = xlogctl->LogwrtResult; if (XLByteLT(xlogctl->asyncXactLSN, asyncXactLSN)) xlogctl->asyncXactLSN = asyncXactLSN; SpinLockRelease(&xlogctl->info_lck); + + /* back off to last completed page boundary */ + WriteRqstPtr.xrecoff -= WriteRqstPtr.xrecoff % XLOG_BLCKSZ; + + /* if we have already flushed that far, we're done */ + if (XLByteLE(WriteRqstPtr, LogwrtResult.Flush)) + return; + + /* + * Nudge the WALWriter if we have a full page of WAL to write. + */ + SetLatch(&XLogCtl->WALWriterLatch); } /* @@ -5072,6 +5093,7 @@ XLOGShmemInit(void) XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages); SpinLockInit(&XLogCtl->info_lck); InitSharedLatch(&XLogCtl->recoveryWakeupLatch); + InitSharedLatch(&XLogCtl->WALWriterLatch); /* * If we are not in bootstrap mode, pg_control should already exist. Read @@ -10013,3 +10035,12 @@ WakeupRecovery(void) { SetLatch(&XLogCtl->recoveryWakeupLatch); } + +/* + * Manage the WALWriterLatch + */ +Latch * +WALWriterLatch(void) +{ + return &XLogCtl->WALWriterLatch; +} diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 23c4aacd7d..157728e20e 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -11,7 +11,8 @@ * * Note that as with the bgwriter for shared buffers, regular backends are * still empowered to issue WAL writes and fsyncs when the walwriter doesn't - * keep up. + * keep up. This means that the WALWriter is not an essential process and + * can shutdown quickly when requested. * * Because the walwriter's cycle is directly linked to the maximum delay * before async-commit transactions are guaranteed committed, it's probably @@ -76,7 +77,6 @@ static void wal_quickdie(SIGNAL_ARGS); static void WalSigHupHandler(SIGNAL_ARGS); static void WalShutdownHandler(SIGNAL_ARGS); - /* * Main entry point for walwriter process * @@ -89,6 +89,8 @@ WalWriterMain(void) sigjmp_buf local_sigjmp_buf; MemoryContext walwriter_context; + InitLatch(WALWriterLatch()); /* initialize latch used in main loop */ + /* * If possible, make this process a group leader, so that the postmaster * can signal any child processes too. (walwriter probably never has any @@ -220,7 +222,7 @@ WalWriterMain(void) */ for (;;) { - long udelay; + ResetLatch(WALWriterLatch()); /* * Emergency bailout if postmaster has died. This is to avoid the @@ -248,20 +250,9 @@ WalWriterMain(void) */ XLogBackgroundFlush(); - /* - * Delay until time to do something more, but fall out of delay - * reasonably quickly if signaled. - */ - udelay = WalWriterDelay * 1000L; - while (udelay > 999999L) - { - if (got_SIGHUP || shutdown_requested) - break; - pg_usleep(1000000L); - udelay -= 1000000L; - } - if (!(got_SIGHUP || shutdown_requested)) - pg_usleep(udelay); + (void) WaitLatch(WALWriterLatch(), + WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, + WalWriterDelay /* ms */); } } @@ -308,6 +299,7 @@ static void WalSigHupHandler(SIGNAL_ARGS) { got_SIGHUP = true; + SetLatch(WALWriterLatch()); } /* SIGTERM: set flag to exit normally */ @@ -315,4 +307,5 @@ static void WalShutdownHandler(SIGNAL_ARGS) { shutdown_requested = true; + SetLatch(WALWriterLatch()); } diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 83106b80e4..6344a850dc 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -16,6 +16,7 @@ #include "datatype/timestamp.h" #include "lib/stringinfo.h" #include "storage/buf.h" +#include "storage/latch.h" #include "utils/pg_crc.h" /* @@ -319,6 +320,7 @@ extern TimeLineID GetRecoveryTargetTLI(void); extern bool CheckPromoteSignal(void); extern void WakeupRecovery(void); +extern Latch *WALWriterLatch(void); /* * Starting/stopping a base backup