对PostgreSQL 的 background writer 的初步理解

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

代码缩略如下:

复制代码
/*                                            
 * 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)                                            
{                                            
    ……                                        
    /*                                        
     * Properly accept or ignore signals the postmaster might send us.                                        
     *                                        
     * bgwriter doesn't participate in ProcSignal signalling, but a SIGUSR1                                        
     * handler is still needed for latch wakeups.                                        
     */                                        
    pqsignal(SIGHUP, BgSigHupHandler);                    /* set flag to read config file */                    
    pqsignal(SIGINT, SIG_IGN);                                        
    pqsignal(SIGTERM, ReqShutdownHandler);                    /* shutdown */                    
    pqsignal(SIGQUIT, bg_quickdie);                    /* hard crash time */                    
    pqsignal(SIGALRM, SIG_IGN);                                        
    pqsignal(SIGPIPE, SIG_IGN);                                        
    pqsignal(SIGUSR1, bgwriter_sigusr1_handler);                                        
    pqsignal(SIGUSR2, SIG_IGN);                                        
                                            
    /*                                        
     * Reset some signals that are accepted by postmaster but not here                                        
     */                                        
    pqsignal(SIGCHLD, SIG_DFL);                                        
    pqsignal(SIGTTIN, SIG_DFL);                                        
    pqsignal(SIGTTOU, SIG_DFL);                                        
    pqsignal(SIGCONT, SIG_DFL);                                        
    pqsignal(SIGWINCH, SIG_DFL);                                        
                                            
    /* We allow SIGQUIT (quickdie) at all times */                                        
    sigdelset(&BlockSig, SIGQUIT);                                        
                                            
    ……                                        
    /*                                        
     * Loop forever                                        
     */                                        
    for (;;)                                        
    {                                        
        bool        can_hibernate;                            
        int        rc;                            
                                            
        /* Clear any already-pending wakeups */                                    
        ResetLatch(&MyProc->procLatch);                                    
                                            
        if (got_SIGHUP)                                    
        {                                    
            got_SIGHUP = false;                                
            ProcessConfigFile(PGC_SIGHUP);                                
        }                                    
        if (shutdown_requested)                                    
        {                                    
            /*                                
             * From here on, elog(ERROR) should end with exit(1), not send                                
             * control back to the sigsetjmp block above                                
             */                                
            ExitOnAnyError = true;                                
            /* Normal exit from the bgwriter is here */                                
            proc_exit(0);        /* done */                        
        }                                    
                                            
        /*                                    
         * Do one cycle of dirty-buffer writing.                                    
         */                                    
        can_hibernate = BgBufferSync();                                    
                                            
        /*                                    
         * Send off activity statistics to the stats collector                                    
         */                                    
        pgstat_send_bgwriter();                                    
                                            
        if (FirstCallSinceLastCheckpoint())                                    
        {                                    
            /*                                
             * After any checkpoint, close all smgr files.                    This is so we            
             * won't hang onto smgr references to deleted files indefinitely.                                
             */                                
            smgrcloseall();                                
        }                                    
                                            
        /*                                    
         * 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);                                
        }                                    
        ……                                    
    }                                        
}                                            
复制代码

我的理解:其中最为关键的就是这一段:

/* 
* Do one cycle of dirty-buffer writing.
*/
can_hibernate = BgBufferSync(); 

其位于 src\backend\storage\buffer 目录下的 bufmgr.c 中。








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

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
9月前
|
SQL Cloud Native 关系型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
ADBPG(AnalyticDB for PostgreSQL)是阿里云提供的一种云原生的大数据分析型数据库
739 1
|
9月前
|
数据可视化 关系型数据库 MySQL
将 PostgreSQL 迁移到 MySQL 数据库
将 PostgreSQL 迁移到 MySQL 数据库
1058 2
|
11月前
|
SQL 关系型数据库 Linux
【PostgreSQL】基于CentOS系统安装PostgreSQL数据库
【PostgreSQL】基于CentOS系统安装PostgreSQL数据库
542 0
|
8月前
|
SQL 存储 自然语言处理
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
在当今社交媒体的时代,人们通过各种平台分享自己的生活、观点和情感。然而,对于平台管理员和品牌经营者来说,了解用户的情感和意见变得至关重要。为了帮助他们更好地了解用户的情感倾向,我们可以使用PostgreSQL中的pg_jieba插件对这些发帖进行分词和情感分析,来构建一个社交媒体情感分析系统,系统将根据用户的发帖内容,自动判断其情感倾向是积极、消极还是中性,并将结果存储在数据库中。
玩转阿里云RDS PostgreSQL数据库通过pg_jieba插件进行分词
|
8月前
|
关系型数据库 测试技术 分布式数据库
PolarDB | PostgreSQL 高并发队列处理业务的数据库性能优化实践
在电商业务中可能涉及这样的场景, 由于有上下游关系的存在, 1、用户下单后, 上下游厂商会在自己系统中生成一笔订单记录并反馈给对方, 2、在收到反馈订单后, 本地会先缓存反馈的订单记录队列, 3、然后后台再从缓存取出订单并进行处理. 如果是高并发的处理, 因为大家都按一个顺序获取, 容易产生热点, 可能遇到取出队列遇到锁冲突瓶颈、IO扫描浪费、CPU计算浪费的瓶颈. 以及在清除已处理订单后, 索引版本未及时清理导致的回表版本判断带来的IO浪费和CPU运算浪费瓶颈等. 本文将给出“队列处理业务的数据库性能优化”优化方法和demo演示. 性能提升10到20倍.
596 4
|
9月前
|
SQL 存储 人工智能
NineData已支持「最受欢迎数据库」PostgreSQL
NineData 也在近期支持了 PostgreSQL,用户可以在 NineData 平台上进行创建数据库/Schema、管理用户与角色、导出数据、执行 SQL 等操作。另外,NineData SQL 开发企业版,还可以统一管理企业内部 PostgreSQL 的访问、规范与流程、变更发布等。
311 0
NineData已支持「最受欢迎数据库」PostgreSQL
|
9月前
|
存储 Cloud Native 关系型数据库
云原生之使用docker部署Postgresql数据库
云原生之使用docker部署Postgresql数据库
320 0
云原生之使用docker部署Postgresql数据库
|
9月前
|
JSON 安全 关系型数据库
PostgreSQL的优势:为何它成为主流数据库管理系统
PostgreSQL的优势:为何它成为主流数据库管理系统
528 0
|
10月前
|
存储 SQL 关系型数据库
触发器:解密PostgreSQL数据库的强大利器
触发器:解密PostgreSQL数据库的强大利器
118 0