diff options
Diffstat (limited to 'src/backend/storage/buffer')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 79 | ||||
-rw-r--r-- | src/backend/storage/buffer/freelist.c | 24 |
2 files changed, 95 insertions, 8 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 */ diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 12d67b13424..84bcb1554d1 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.35 2003/11/16 16:41:00 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.36 2003/11/19 15:55:07 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -190,8 +190,28 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) if (StrategyControl->stat_report + DebugSharedBuffers < now) { long all_hit, b1_hit, t1_hit, t2_hit, b2_hit; + int id, t1_clean, t2_clean; ErrorContextCallback *errcxtold; + id = StrategyControl->listHead[STRAT_LIST_T1]; + t1_clean = 0; + while (id >= 0) + { + if (BufferDescriptors[StrategyCDB[id].buf_id].flags & BM_DIRTY) + break; + t1_clean++; + id = StrategyCDB[id].next; + } + id = StrategyControl->listHead[STRAT_LIST_T2]; + t2_clean = 0; + while (id >= 0) + { + if (BufferDescriptors[StrategyCDB[id].buf_id].flags & BM_DIRTY) + break; + t2_clean++; + id = StrategyCDB[id].next; + } + if (StrategyControl->num_lookup == 0) { all_hit = b1_hit = t1_hit = t2_hit = b2_hit = 0; @@ -215,6 +235,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) T1_TARGET, B1_LENGTH, T1_LENGTH, T2_LENGTH, B2_LENGTH); elog(DEBUG1, "ARC total =%4ld%% B1hit=%4ld%% T1hit=%4ld%% T2hit=%4ld%% B2hit=%4ld%%", all_hit, b1_hit, t1_hit, t2_hit, b2_hit); + elog(DEBUG1, "ARC clean buffers at LRU T1= %5d T2= %5d", + t1_clean, t2_clean); error_context_stack = errcxtold; StrategyControl->num_lookup = 0; |