• innodb中master线程的调度的算法改进(mysql 5.6.26)


                innodb中master线程的调度的算法改进(mysql 5.6.26)
                   作者:周琳
                   QQ:715169549
                   源码交流群:196380905
                
    1.master线程的调度:
     /*********************************************************************//**
     The master thread controlling the server.
    os_thread_ret_t DECLARE_THREAD(srv_master_thread)
    如下是核心代码:
                    ulint        old_activity_count = srv_get_activity_count();
                    if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
                        goto suspend_thread;
                    }
                    while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
    
                        /*在linux下就是1000000/1000000,在针对这个整除的值%1000000;
                        *这个就是os_thread_sleep( microseconds);的计算方式
                        srv_master_sleep(); //
    
                        MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);
                        /*很显然并没有按照1秒和10秒的算法来,而是通过当前服务器活动的数量来决定。
                        if (srv_check_activity(old_activity_count)) { //srv_check_activity(old_activity_count)返回:return(srv_sys->activity_count != old_activity_count);
                            old_activity_count = srv_get_activity_count(); //srv_get_activity_count返回:return(srv_sys->activity_count);
                            srv_master_do_active_tasks();
                        } else {
                            srv_master_do_idle_tasks();
                        }
                    }
    
                    while (srv_master_do_shutdown_tasks(&last_print_time)) {
    
                        /* Shouldn't loop here in case of very fast shutdown */
                        ut_ad(srv_fast_shutdown < 2);
                    }
                }
     srv_master_do_active_tasks做的事情:
        //#define PCT_IO(p) ((ulong) (srv_io_capacity * ((double) (p) / 100.0)))
        //# define    SRV_MASTER_CHECKPOINT_INTERVAL        (7)
        1.log_free_check,检查是否有空闲的log buffer。
        2.ibuf_contract_in_background(0, FALSE),合并PCT_IO(5)个插入缓冲
        3.srv_sync_log_buffer_in_background,后台同步刷新log buffer日志到log file
        4.cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0,就做log_checkpoint(TRUE, FALSE),而log_checkpoint仅仅是检查bp中的lsn以及把lsn的值写入到redo file中。
          真正做检查点刷新脏页到磁盘的是log_make_checkpoint_at函数。
          
     srv_master_do_idle_tasks做的事情:
        1.log_free_check,检查是否有空闲的log buffer。
        2.ibuf_contract_in_background(0, TRUE),合并PCT_IO(100)个插入缓冲.
        3.srv_sync_log_buffer_in_background,刷新log buffer到磁盘。
        4.cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0,就做log_checkpoint(TRUE, FALSE),而log_checkpoint仅仅是检查bp中的lsn以及把lsn的值写入到redo file中。
          真正做检查点刷新脏页到磁盘的是log_make_checkpoint_at函数。
          
          如下是srv_sys_t结构:
             元素包含一个线程表和一个task queue。
                /** The server system struct */
                struct srv_sys_t{
                    ib_mutex_t    tasks_mutex;        /*!< variable protecting the
                                        tasks queue */
                    UT_LIST_BASE_NODE_T(que_thr_t)
                            tasks;            /*!< task queue */
    
                    ib_mutex_t    mutex;            /*!< variable protecting the
                                        fields below. */
                    ulint        n_sys_threads;        /*!< size of the sys_threads
                                        array */
    
                    srv_slot_t*    sys_threads;        /*!< server thread table */
    
                    ulint        n_threads_active[SRV_MASTER + 1];
                                        /*!< number of threads active
                                        in a thread class */
    
                    srv_stats_t::ulint_ctr_1_t
                            activity_count;        /*!< For tracking server
                                        activity */
                };
         接下来介绍下activity_count,这个函数是由srv_inc_activity_count(srv_sys->activity_count.inc();)进行自增的,这个函数会在哪些动作中调用呢?
         我们看下调用该函数的函数流程:
            1.row_undo_step:在表中回滚一行的操作
                 ->srv_inc_activity_count()
            2.srv_active_wake_master_thread:如果需要主线程处理,切主线程处于挂起状态就唤醒主线程。
                 ->srv_inc_activity_count()
            3.srv_wake_master_thread:如果主线程挂起或者正在被挂起,唤醒主线程。
                 ->srv_inc_activity_count()
             上述函数还被很多函数调用,activity_count可以理解为mysql运行中操作的计数器,每个操作都会累加。所以master线程依据时间间隔的
        activity_count计数器来判断执行srv_master_do_active_tasks还是srv_master_do_idle_tasks。可以看出这个计数器如果在1秒以后这个值如果
        不发生变化就切换到srv_master_do_idle_tasks。
        
    2.page cleaner线程:(buf0flu.c中)
        核心代码:    
               ulint    next_loop_time = ut_time_ms() + 1000;
                while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {//服务器没有关闭的状态下
    
                    /* The page_cleaner skips sleep if the server is
                    idle and there are no pending IOs in the buffer pool
                    and there is work to do. */
                    if (srv_check_activity(last_activity) //检查当前服务器的活动次数
                        || buf_get_n_pending_read_ios()
                        || n_flushed == 0) {
                        page_cleaner_sleep_if_needed(next_loop_time); //休眠min(1000000,(next_loop_time-当前时间)*1000))
                    }
    
                    next_loop_time = ut_time_ms() + 1000; //重新计算当前next_loop_time值
    
                    if (srv_check_activity(last_activity)) { //检查当前服务器活动数量
                        last_activity = srv_get_activity_count();
    
                        /* Flush pages from end of LRU if required */
                        n_flushed = buf_flush_LRU_tail(); 
    
                        /* Flush pages from flush_list if required */
                        n_flushed += page_cleaner_flush_pages_if_needed();
                    } else {
                        n_flushed = page_cleaner_do_flush_batch(
                                        PCT_IO(100),  //刷新srv_io_capacity个脏页到磁盘
                                        LSN_MAX);
                    }
        }
        if (srv_fast_shutdown == 2) {
            /* In very fast shutdown we simulate a crash of
            buffer pool. We are not required to do any flushing */
            goto thread_exit;
        }
        do {
            n_flushed = page_cleaner_do_flush_batch(PCT_IO(100), LSN_MAX); //刷新srv_io_capacity个脏页到磁盘
    
            /* We sleep only if there are no pages to flush */
            if (n_flushed == 0) {
                os_thread_sleep(100000); //休眠1秒
            }
        } while (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
        do {
    
            success = buf_flush_list(PCT_IO(100), LSN_MAX, &n_flushed);
            buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
    
        } while (!success || n_flushed > 0);
        
  • 相关阅读:
    (三)通用定时器的定时功能(不使用中断)
    (二)STM32中中断优先级理解
    (一)通用定时器的相关介绍
    Ambari client
    Ambari的资源池管理
    Sentry的授权模型
    关于yum
    Ambari-HDP
    Ambari的API调用
    CentOS上面搭建SVN服务器
  • 原文地址:https://www.cnblogs.com/innobase/p/4726663.html
Copyright © 2020-2023  润新知