iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中AutoVacLauncherMain函数的实现逻辑是什么
  • 601
分享到

PostgreSQL中AutoVacLauncherMain函数的实现逻辑是什么

2024-04-02 19:04:59 601人浏览 薄情痞子
摘要

本篇内容介绍了“postgresql中AutoVacLauncherMain函数的实现逻辑是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况

本篇内容介绍了“postgresql中AutoVacLauncherMain函数的实现逻辑是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、数据结构

宏定义

#define GetProcessingMode() Mode
#define SetProcessingMode(mode) \
    do { \
        AssertArg((mode) == BootstrapProcessing || \
                  (mode) == InitProcessing || \
                  (mode) == NORMalProcessing); \
        Mode = (mode); \
    } while(0)

二、源码解读

AutoVacLauncherMain函数,autovacuum进程主循环.


NON_EXEC_STATIC void
AutoVacLauncherMain(int arGC, char *argv[])
{
    sigjmp_buf  local_sigjmp_buf;
    am_autovacuum_launcher = true;
    
    //进程ID
    init_ps_display(pgstat_get_backend_desc(B_AUTOVAC_LAUNCHER), "", "", "");
    ereport(DEBUG1,
            (errmsg("autovacuum launcher started")));
    if (PostAuthDelay)
        pg_usleep(PostAuthDelay * 1000000L);
    //设置进程模式
    SetProcessingMode(InitProcessing);
    
    pqsignal(SIGHUP, av_sighup_handler);
    pqsignal(SIGINT, StatementCancelHandler);
    pqsignal(SIGTERM, avl_sigterm_handler);
    pqsignal(SIGQUIT, quickdie);
    //建立SIGALRM控制器
    InitializeTimeouts();       
    pqsignal(SIGPIPE, SIG_IGN);//忽略SIGPIPE
    pqsignal(SIGUSR1, procsignal_sigusr1_handler);
    pqsignal(SIGUSR2, avl_sigusr2_handler);
    pqsignal(SIGFPE, FloatExceptionHandler);
    pqsignal(SIGCHLD, SIG_DFL);
    
    //基础初始化
    BaseInit();
    
#ifndef EXEC_BACKEND
    InitProcess();
#endif
    //初始化
    InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false);
    //设置进程模式
    SetProcessingMode(NormalProcessing);
    
    AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
                                          "Autovacuum Launcher",
                                          ALLOCSET_DEFAULT_SIZES);
    MemoryContextSwitchTo(AutovacMemCxt);
    
    if (sigsetjmp(local_sigjmp_buf, 1) != 0)
    {
        
        //由于没有使用PG_TRY,这里必须手工重置错误.
        error_context_stack = NULL;
        
        //在清理期间禁用中断
        HOLD_INTERRUPTS();
        
        //忽略所有QueryCancel或者超时请求
        disable_all_timeouts(false);
        QueryCancelPending = false; 
        
        //在服务器日志中记录日志.
        EmitErrorReport();
        
        //废弃当前事务,以准备恢复
        AbortCurrentTransaction();
        
        LWLockReleaseAll();
        pgstat_report_wait_end();
        AbortBufferIO();
        UnlockBuffers();
        
        //这可能是dead code,但可以保证安全
        if (AuxProcessResourceOwner)
            ReleaseAuxProcessResources(false);
        AtEOXact_Buffers(false);
        AtEOXact_SMgr();
        AtEOXact_Files(false);
        AtEOXact_HashTables(false);
        
        MemoryContextSwitchTo(AutovacMemCxt);
        FlushErrorState();
        
        //在top-level上下文刷新所有泄漏的数据
        MemoryContextResetAndDeleteChildren(AutovacMemCxt);
        
        //不要留下悬空指针来释放内存
        DatabaseListCxt = NULL;
        dlist_init(&DatabaseList);
        
        pgstat_clear_snapshot();
        
        //可以允许中断了
        RESUME_INTERRUPTS();
        
        //如处于shutdown模式,不需要继续后续的工作了,跳转到shutdown
        if (Got_SIGTERM)
            goto shutdown;
        
        pg_usleep(1000000L);
    }
    
    //现在可以处理ereport(ERROR)了
    PG_exception_stack = &local_sigjmp_buf;
    
    //在调用rebuild_database_list前不能阻塞信号
    PG_SETMASK(&UnBlockSig);
    
    SetConfigOption("search_path", "", PGC_SUSET, PGC_S_OVERRIDE);
    
    SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE);
    
    SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
    SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE);
    SetConfigOption("idle_in_transaction_session_timeout", "0",
                    PGC_SUSET, PGC_S_OVERRIDE);
    
    SetConfigOption("default_transaction_isolation", "read committed",
                    PGC_SUSET, PGC_S_OVERRIDE);
    
    if (!AutoVacuumingActive())
    {
        if (!got_SIGTERM)
            do_start_worker();
        proc_exit(0);           
    }
    AutoVacuumShmem->av_launcherpid = MyProcPid;
    
    rebuild_database_list(InvalidOid);
    
    //循环,直至请求shutdown
    while (!got_SIGTERM)
    {
        struct timeval nap;
        TimestampTz current_time = 0;
        bool        can_launch;
        
        launcher_determine_sleep(!dlist_is_empty(&AutoVacuumShmem->av_freeWorkers),
                                 false, &nap);
        
        (void) WaitLatch(MyLatch,
                         WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
                         (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
                         WAIT_EVENT_AUTOVACUUM_MAIN);
        ResetLatch(MyLatch);
        
        //在休眠过程中,进程会捕获相关的中断.
        ProcessCatchupInterrupt();
        
        //shutdonw信号
        if (got_SIGTERM)
            break;
        if (got_SIGHUP)
        {
            //SIGHUP信号
            got_SIGHUP = false;
            ProcessConfigFile(PGC_SIGHUP);
            
            //在配置文件中已请求shutdown?
            if (!AutoVacuumingActive())
                break;
            
            //如默认的成本参数变化,则自动平衡.
            LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
            autovac_balance_cost();
            LWLockRelease(AutovacuumLock);
            
            //如naptime出现变化,重建链表
            rebuild_database_list(InvalidOid);
        }
        
        if (got_SIGUSR2)
        {
            //SIGUSR2信号
            got_SIGUSR2 = false;
            
            //如需要,重平衡成本限制
            if (AutoVacuumShmem->av_signal[AutoVacRebalance])
            {
                LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
                AutoVacuumShmem->av_signal[AutoVacRebalance] = false;
                autovac_balance_cost();
                LWLockRelease(AutovacuumLock);
            }
            if (AutoVacuumShmem->av_signal[AutoVacForkFailed])
            {
                
                AutoVacuumShmem->av_signal[AutoVacForkFailed] = false;
                pg_usleep(1000000L);    
                SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER);
                continue;
            }
        }
        
        current_time = GetCurrentTimestamp();
        LWLockAcquire(AutovacuumLock, LW_SHARED);
        can_launch = !dlist_is_empty(&AutoVacuumShmem->av_freeWorkers);
        if (AutoVacuumShmem->av_startingWorker != NULL)
        {
            int         waittime;
            WorkerInfo  worker = AutoVacuumShmem->av_startingWorker;
            
            waittime = Min(autovacuum_naptime, 60) * 1000;
            if (TimestampDifferenceExceeds(worker->wi_launchtime, current_time,
                                           waittime))
            {
                LWLockRelease(AutovacuumLock);
                LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
                
                if (AutoVacuumShmem->av_startingWorker != NULL)
                {
                    worker = AutoVacuumShmem->av_startingWorker;
                    worker->wi_dboid = InvalidOid;
                    worker->wi_tableoid = InvalidOid;
                    worker->wi_sharedrel = false;
                    worker->wi_proc = NULL;
                    worker->wi_launchtime = 0;
                    dlist_push_head(&AutoVacuumShmem->av_freeWorkers,
                                    &worker->wi_links);
                    AutoVacuumShmem->av_startingWorker = NULL;
                    elog(WARNING, "worker took too long to start; canceled");
                }
            }
            else
                can_launch = false;
        }
        //释放
        LWLockRelease(AutovacuumLock);  
        
        //什么都做不了,继续休眠
        if (!can_launch)
            continue;
        
        //现在可以启动新的worker  
        if (dlist_is_empty(&DatabaseList))
        {
            
            launch_worker(current_time);
        }
        else
        {
            
            avl_dbase  *avdb;
            avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
            
            if (TimestampDifferenceExceeds(avdb->adl_next_worker,
                                           current_time, 0))
                launch_worker(current_time);
        }
    }
    
    //常规的退出.
shutdown:
    ereport(DEBUG1,
            (errmsg("autovacuum launcher shutting down")));
    AutoVacuumShmem->av_launcherpid = 0;
    proc_exit(0);               
}

“Postgresql中AutoVacLauncherMain函数的实现逻辑是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中AutoVacLauncherMain函数的实现逻辑是什么

本文链接: https://www.lsjlt.com/news/64260.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作