diff options
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index cbb23b664c6..aab99caa9d6 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.144 2003/11/13 14:57:15 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.145 2003/11/19 15:55:07 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -44,6 +44,7 @@ #include <sys/file.h> #include <math.h> #include <signal.h> +#include <unistd.h> #include "lib/stringinfo.h" #include "miscadmin.h" @@ -63,6 +64,9 @@ /* GUC variable */ bool zero_damaged_pages = false; +int BgWriterDelay = 200; +int BgWriterPercent = 1; +int BgWriterMaxpages = 100; static void WaitIO(BufferDesc *buf); static void StartBufferIO(BufferDesc *buf, bool forInput); @@ -679,10 +683,11 @@ ReleaseAndReadBuffer(Buffer buffer, /* * BufferSync -- Write all dirty buffers in the pool. * - * This is called at checkpoint time and writes out all dirty shared buffers. + * This is called at checkpoint time and writes out all dirty shared buffers, + * and by the background writer process to write out some of the dirty blocks. */ -void -BufferSync(void) +int +BufferSync(int percent, int maxpages) { int i; BufferDesc *bufHdr; @@ -703,12 +708,24 @@ BufferSync(void) * have to wait until the next checkpoint. */ buffer_dirty = (int *)palloc(NBuffers * sizeof(int)); - num_buffer_dirty = 0; - + LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); num_buffer_dirty = StrategyDirtyBufferList(buffer_dirty, NBuffers); LWLockRelease(BufMgrLock); + /* + * If called by the background writer, we are usually asked to + * only write out some percentage of dirty buffers now, to prevent + * the IO storm at checkpoint time. + */ + if (percent > 0 && num_buffer_dirty > 10) + { + Assert(percent <= 100); + num_buffer_dirty = (num_buffer_dirty * percent) / 100; + if (maxpages > 0 && num_buffer_dirty > maxpages) + num_buffer_dirty = maxpages; + } + for (i = 0; i < num_buffer_dirty; i++) { Buffer buffer; @@ -854,6 +871,8 @@ BufferSync(void) /* Pop the error context stack */ error_context_stack = errcontext.previous; + + return num_buffer_dirty; } /* @@ -984,10 +1003,56 @@ AtEOXact_Buffers(bool isCommit) void FlushBufferPool(void) { - BufferSync(); + BufferSync(-1, -1); smgrsync(); } + +/* + * BufferBackgroundWriter + * + * Periodically flushes dirty blocks from the buffer pool to keep + * the LRU list clean, preventing regular backends from writing. + */ +void +BufferBackgroundWriter(void) +{ + if (BgWriterPercent == 0) + return; + + /* + * Loop forever + */ + for (;;) + { + int n, i; + + /* + * Call BufferSync() with instructions to keep just the + * LRU heads clean. + */ + n = BufferSync(BgWriterPercent, BgWriterMaxpages); + + /* + * Whatever signal is sent to us, let's just die galantly. If + * it wasn't meant that way, the postmaster will reincarnate us. + */ + if (InterruptPending) + return; + + /* + * Nap for the configured time or sleep for 10 seconds if + * there was nothing to do at all. + */ + if (n > 0) + { + PG_DELAY(BgWriterDelay); + } + else + sleep(10); + } +} + /* * Do whatever is needed to prepare for commit at the bufmgr and smgr levels */ |