bgwriter 的睡眠时间差异

开始

简单说就是一开始启动的很频繁(200ms 级),后来没有什么事情可做,就懒惰了。变成了 10秒级别。

实际验证如下

postgresql.conf 中和 log 相关部分:

log_line_prefix = '%m'        

log_min_messages = info        

logging_collector = off        

对 bufmgr.c 的 BgBufferSync的调试:

bool                

BgBufferSync(void)                

{                

                

    ……            

    /* Execute the LRU scan */            

    while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)            

    {            

                

                        //added by gaojian        

                        fprintf(stderr,"num_to_scan is: %d \n",num_to_scan);        

                

        int    buffer_state = SyncOneBuffer(next_to_clean, true);    

                

        if (++next_to_clean >= NBuffers)        

        {        

            next_to_clean = 0;    

                

            elog(INFO,"------------------next_passes++.\n");    

            next_passes++;    

        }        

        num_to_scan--;        

                

        if (buffer_state & BUF_WRITTEN)        

        {        

            reusable_buffers++;    

            if (++num_written >= bgwriter_lru_maxpages)    

            {    

                BgWriterStats.m_maxwritten_clean++;

                break;

            }    

        }        

        else if (buffer_state & BUF_REUSABLE)        

            reusable_buffers++;    

    }            

                

    elog(INFO,".......BgBufferSync Called.");            

    /* Return true if OK to hibernate */            

    return (bufs_to_lap == 0 && recent_alloc == 0);            

}                

                

运行的结果是:

[作者:技术者高健@博客园  mail: [email protected] ]

[postgres@localhost bin]$ ./postgres -D /usr/local/pgsql/data

2012-11-02 16:09:55.139 CSTLOG:  database system was shut down at 2012-11-02 16:01:26 CST

saved_info_valid false.

2012-11-02 16:09:55.199 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:09:55.199 CSTLOG:  autovacuum launcher started

2012-11-02 16:09:55.201 CSTLOG:  database system is ready to accept connections

2012-11-02 16:09:55.399 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:09:55.599 CSTINFO:  .......BgBufferSync Called.





……



2012-11-02 16:12:11.350 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:11.550 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:11.751 CSTINFO:  ------------------next_passes++.



2012-11-02 16:12:11.751 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:11.951 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:12.151 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:22.360 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:32.568 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:42.777 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:12:52.985 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:13:03.194 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:13:13.403 CSTINFO:  .......BgBufferSync Called.



2012-11-02 16:13:23.614 CSTINFO:  .......BgBufferSync Called.

bgwriter 会在循环中 睡眠-->醒来->调用BgBufferSync-->睡眠。

基本上,其睡眠应该分”浅睡眠“和”深睡眠“

再回头来看 bgwriter.c 的代码:

/*                            

 * GUC parameters                            

 */                            

int            BgWriterDelay = 200;                

                            

/*                            

 * Multiplier to apply to BgWriterDelay when we decide to hibernate.                            

 * (Perhaps this needs to be configurable?)                            

 */                            

#define HIBERNATE_FACTOR            50                

                            

……                            

                            

/*                            

 * Main entry point for bgwriter process                            

 *                            

 * This is invoked from AuxiliaryProcessMain, which has already created the                            

 * basic execution environment, but not enabled signals yet.                            

 */                            

void                            

BackgroundWriterMain(void)                            

{                            

    ……                        

    /*                        

     * Loop forever                        

     */                        

    for (;;)                        

    {                        

        ……                    

                            

        /*                    

         * Sleep until we are signaled or BgWriterDelay has elapsed.                    

         *                    

         * Note: the feedback control loop in BgBufferSync() expects that we                    

         * will call it every BgWriterDelay msec.  While it's not critical for                    

         * correctness that that be exact, the feedback loop might misbehave                    

         * if we stray too far from that.  Hence, avoid loading this process                    

         * down with latch events that are likely to happen frequently during                    

         * normal operation.                    

         */                    

        rc = WaitLatch(&MyProc->procLatch,                    

                       WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,        

                       BgWriterDelay /* ms */ );        

                            

        /*                    

         * If no latch event and BgBufferSync says nothing's happening, extend                    

         * the sleep in "hibernation" mode, where we sleep for much longer                    

         * than bgwriter_delay says.  Fewer wakeups save electricity.  When a                    

         * backend starts using buffers again, it will wake us up by setting                    

         * our latch.  Because the extra sleep will persist only as long as no                    

         * buffer allocations happen, this should not distort the behavior of                    

         * BgBufferSync's control loop too badly; essentially, it will think                    

         * that the system-wide idle interval didn't exist.                    

         *                    

         * There is a race condition here, in that a backend might allocate a                    

         * buffer between the time BgBufferSync saw the alloc count as zero                    

         * and the time we call StrategyNotifyBgWriter.  While it's not                    

         * critical that we not hibernate anyway, we try to reduce the odds of                    

         * that by only hibernating when BgBufferSync says nothing's happening                    

         * for two consecutive cycles.    Also, we mitigate any possible                

         * consequences of a missed wakeup by not hibernating forever.                    

         */                    

        if (rc == WL_TIMEOUT && can_hibernate && prev_hibernate)                    

        {                    

            /* Ask for notification at next buffer allocation */                

            StrategyNotifyBgWriter(&MyProc->procLatch);                

                            

                            

            /* Sleep ... */                

            rc = WaitLatch(&MyProc->procLatch,                

                           WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,    

                           BgWriterDelay * HIBERNATE_FACTOR);    

            /* Reset the notification request in case we timed out */                

            StrategyNotifyBgWriter(NULL);                

        }                    

        ……                    

    }                        

}                            

可以看到,一开始是睡   BgWriterDelay 就会醒。

然后,睡了若干次再醒后,如果发现  (rc == WL_TIMEOUT && can_hibernate && prev_hibernate) 得到了满足。

那么, 就进入新的睡眠模式:

/* Sleep ... */
rc = WaitLatch(&MyProc->procLatch,
    WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
      BgWriterDelay * HIBERNATE_FACTOR);

最后一个参数变成了  BgWriterDelay * HIBERNATE_FACTOR 正好等于 10秒。

[作者:技术者高健@博客园  mail: [email protected] ]

结束

你可能感兴趣的:(Writer)