• 对PostgreSQL 的 background writer 的初步理解


    代码缩略如下:

    /*                                            
     * 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 中。

  • 相关阅读:
    [CSAPP笔记][第一章计算机系统漫游]
    [暂停学习几天]
    [汇编学习笔记][第十七章使用BIOS进行键盘输入和磁盘读写
    [汇编学习笔记][第十六章直接定址表]
    [汇编语言学习笔记][第十五章 外中断]
    [汇编学习笔记][第十四章 端口]
    [汇编学习笔记][第十三章int指令]
    [汇编学习笔记][第十二章内中断]
    [汇编学习笔记][第十一章标志寄存器]
    [汇编学习笔记][第十章 CALL和RET指令]
  • 原文地址:https://www.cnblogs.com/gaojian/p/2737175.html
Copyright © 2020-2023  润新知