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: luckyjackgao@gmail.com ]

复制代码
[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秒。






本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/11/02/2751502.html,如需转载请自行联系原作者

目录
相关文章
|
7月前
|
前端开发 JavaScript 安全
剖析跨域问题始末及其解决方案——前端必备交叉知识(一)
跨域问题是前端开发中的常见挑战,了解并掌握不同的跨域解决方案能帮助你更高效地进行开发工作。本文对同源策略、跨域以及解决跨域的三种方案: CORS、JSONP、代理等跨域技术进行了介绍。选择合适的跨域解决方案非常重要。 在实际开发中,推荐优先考虑使用 CORS,因为它是现代浏览器支持的标准,且安全性较高。如果服务器无法修改,则可以考虑使用代理。如果是特殊情况,可以使用 JSONP,但要注意安全性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
在操作系统中,进程间通信(IPC)是至关重要的,它提供了多种机制来实现不同进程间的数据交换和同步。本篇文章将详细介绍几种常见的IPC方式,包括管道、信号、消息队列、共享内存、信号量和套接字,帮助你深入理解并合理应用这些通信方式,提高系统性能与可靠性。
693 0
|
网络安全 网络架构
traceroute命令详解
traceroute命令详解
|
架构师 开发工具 C++
最新python--类与面向对象-1,一线互联网架构师360°全方面性能调优
最新python--类与面向对象-1,一线互联网架构师360°全方面性能调优
最新python--类与面向对象-1,一线互联网架构师360°全方面性能调优
|
运维 关系型数据库 分布式数据库
PolarDB产品使用问题之如何将普通表转换为分区表
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
237 0
|
NoSQL BI MongoDB
MongoDB 数据探索之道:查询文档操作详解
MongoDB 数据探索之道:查询文档操作详解
154 0
|
消息中间件 缓存 前端开发
【Docker学习笔记 二】Docker安装、运行流程与常用命令
【Docker学习笔记 二】Docker安装、运行流程与常用命令
1525 0
|
安全 Java 测试技术
发生死锁怎么办
发生死锁怎么办
117 0
|
存储 数据采集 NoSQL
JWT本无状态,为何却要存储在Redis破坏其无状态特性?
JWT本无状态,为何却要存储在Redis破坏其无状态特性?
803 0
JWT本无状态,为何却要存储在Redis破坏其无状态特性?