`

mysql5.5.25 源码阅读---innodb 主线程工作流程

阅读更多
srv0src.cc

srv_master_thread(void* arg __attribute__((unused)))
{
      ## 省略各种变量声明、赋值
loop:
/*****************************************************************/
/* ---- When there is database activity by users, we cycle in this
loop */

srv_main_thread_op_info = "reserving kernel mutex";

        ## 获取bp的统计信息
buf_get_total_stat(&buf_stat);

n_ios_very_old = log_sys->n_log_ios + buf_stat.n_pages_read
+ buf_stat.n_pages_written;
mutex_enter(&kernel_mutex);

/* Store the user activity counter at the start of this loop */
old_activity_count = srv_activity_count;

mutex_exit(&kernel_mutex);

if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {

goto suspend_thread;
}

/* ---- We run the following loop approximately once per second
when there is database activity */

srv_last_log_flush_time = time(NULL);

/* Sleep for 1 second on entrying the for loop below the first time. */
next_itr_time = ut_time_ms() + 1000;

每1秒进行的工作
        for (i = 0; i < 10; i++) {
ulint cur_time = ut_time_ms();

/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
queries to them. */
srv_main_thread_op_info = "doing background drop tables";

                ## ALTER TABLE产生的drop tables lazily信息
row_drop_tables_for_mysql_in_background();

srv_main_thread_op_info = "";

if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto background_loop;
}

                ## 获取bp的统计信息
buf_get_total_stat(&buf_stat);

n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
+ buf_stat.n_pages_written;

srv_main_thread_op_info = "sleeping";
srv_main_1_second_loops++;

                ## 可能sleep 1秒
if (next_itr_time > cur_time
    && srv_shutdown_state == SRV_SHUTDOWN_NONE) {

/* Get sleep interval in micro seconds. We use
ut_min() to avoid long sleep in case of
wrap around. */
os_thread_sleep(ut_min(1000000,
(next_itr_time - cur_time)
* 1000));
srv_main_sleeps++;
}

/* Each iteration should happen at 1 second interval. */
next_itr_time = ut_time_ms() + 1000;

                ## flush log buffer
srv_sync_log_buffer_in_background();

                ## 检查是否要进行flush log buffer 或者产生一个新的checkpoint
srv_main_thread_op_info = "making checkpoint";
                log_free_check();

/* If i/os during one second sleep were less than 5% of
capacity, we assume that there is free disk i/o capacity
available, and it makes sense to do an insert buffer merge. */

                ## 获取bp的统计信息
buf_get_total_stat(&buf_stat);

                ## 可能merge最多5个insert buffer
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
+ buf_stat.n_pages_written;
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
    && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
ibuf_contract_for_n_pages(FALSE, PCT_IO(5));

/* Flush logs if needed */
srv_sync_log_buffer_in_background();
}

                ## 根据BP的脏页比例, 可能则flush最多100个脏页
if (UNIV_UNLIKELY(buf_get_modified_ratio_pct()
  > srv_max_buf_pool_modified_pct)) {
n_pages_flushed = buf_flush_list(
PCT_IO(100), IB_ULONGLONG_MAX);

} else if (srv_adaptive_flushing) {
ulint n_flush = buf_flush_get_desired_flush_rate();

if (n_flush) {
n_flush = ut_min(PCT_IO(100), n_flush);
n_pages_flushed =
                                      buf_flush_list(n_flush,IB_ULONGLONG_MAX);
}
}

                ## 检查是否存在活动用户
if (srv_activity_count == old_activity_count) {
goto background_loop;
}
}

        每1秒的工作结束

        每10秒的工作开始
/* ---- We perform the following code approximately once per
10 seconds when there is database activity */


        ## 获取bp的统计信息
buf_get_total_stat(&buf_stat);

n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
+ buf_stat.n_pages_written;

srv_main_10_second_loops++;

        ## io使用情况, 可能则flush最多100个脏页
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
    && (n_ios - n_ios_very_old < SRV_PAST_IO_ACTIVITY)) {
buf_flush_list(PCT_IO(100), IB_ULONGLONG_MAX);

                ## flush log buffer
srv_sync_log_buffer_in_background();
}

        ## merge 5个insert buffer
srv_main_thread_op_info = "doing insert buffer merge";
ibuf_contract_for_n_pages(FALSE, PCT_IO(5));

        ## flush log buffer
srv_sync_log_buffer_in_background();

        ## 未启用purge thread,则full purge。即删除BP中无用的undo页
if (srv_n_purge_threads == 0) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
}

        ## 检查BP的脏页比例是否大于70%,flush 100或10个脏页
srv_main_thread_op_info = "flushing buffer pool pages";
if (buf_get_modified_ratio_pct() > 70) {
               ## flush BP中 100 个脏页
n_pages_flushed = buf_flush_list(PCT_IO(100), IB_ULONGLONG_MAX);
} else {
               ## flush BP中 10 个脏页
n_pages_flushed = buf_flush_list(PCT_IO(10), IB_ULONGLONG_MAX);
}

        ## 产生一个checkpoint
srv_main_thread_op_info = "making checkpoint";
log_checkpoint(TRUE, FALSE);

srv_main_thread_op_info = "reserving kernel mutex";

        每10秒的工作结束
       
        ## 检查是跳回loop还是进入background_loop
mutex_enter(&kernel_mutex);
        if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex);

background_loop:
srv_main_background_loops++;
srv_main_thread_op_info = "doing background drop tables";

        ## ALTER TABLE产生的drop tables lazily信息
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
if (n_tables_to_drop > 0) {
/* Do not monopolize the CPU even if there are tables waiting
in the background drop queue. (It is essentially a bug if
MySQL tries to drop a table while there are still open handles
to it and we had to put it to the background drop queue.) */

if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
os_thread_sleep(100000);
}
}

        ## 未启用purge thread,则full purge。即删除BP中无用的undo页
if (srv_n_purge_threads == 0) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
}

        ## 检查是跳回loop还是继续
srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex);

        ## 根据srv_fast_shutdown配置
             是否merge最多100个insert buffer

srv_main_thread_op_info = "doing insert buffer merge";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
n_bytes_merged = 0;
} else {
n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
   PCT_IO(100));
}

        ## 检查是跳回loop还是进入 flush loop
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex);

flush_loop:
srv_main_thread_op_info = "flushing buffer pool pages";
srv_main_flush_loops++;
        ## srv_fast_shutdown<2,从LFU中flush最多100个 dirty page
if (srv_fast_shutdown < 2) {
n_pages_flushed = buf_flush_list(
  PCT_IO(100), IB_ULONGLONG_MAX);
} else {
/* In the fastest shutdown we do not flush the buffer pool
to data files: we set n_pages_flushed to 0 artificially. */

n_pages_flushed = 0;
}

        ## 检查是跳回loop还是继续
srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex);

        ## 将LFU所有脏页进行flush,直到有flush结束信号
srv_main_thread_op_info = "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);

        ## merge insert buffer
srv_sync_log_buffer_in_background();

        ## 产生 checkpoint
srv_main_thread_op_info = "making checkpoint";
log_checkpoint(TRUE, FALSE);

        ## 根据脏页比较是否继续flush_loop
if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
goto flush_loop;
}

        ## 检查是跳回loop还是继续
srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
mutex_exit(&kernel_mutex);

        ## log归档检查
/*
srv_main_thread_op_info = "archiving log (if log archive is on)";
log_archive_do(FALSE, &n_bytes_archived);
*/
n_bytes_archived = 0;
/* Print progress message every 60 seconds during shutdown */
if (srv_shutdown_state > 0 && srv_print_verbose_log) {
srv_shutdown_print_master_pending(&last_print_time,
  n_tables_to_drop,
  n_bytes_merged,
  n_pages_flushed);
}

        ##
             是否有ALTER TABLE产生的drop tables lazily信息
             是否有新的脏页需要flush
             是否有log需要archive
             重新跳回background_loop       
       

if (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_tables_to_drop + n_pages_flushed
    + n_bytes_archived != 0) {
goto background_loop;
}
} else if (n_tables_to_drop
   + n_pages_purged + n_bytes_merged + n_pages_flushed
   + n_bytes_archived != 0) {
goto background_loop;
}

/* There is no work for background operations either: suspend
master thread to wait for more server activity */
        ##   mysql挂起,等待事件发生
suspend_thread:
srv_main_thread_op_info = "suspending";

mutex_enter(&kernel_mutex);

if (row_get_background_drop_list_len_low() > 0) {
mutex_exit(&kernel_mutex);
goto loop;
}

srv_suspend_thread(slot);

mutex_exit(&kernel_mutex);

/* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
waits for database activity to die down when converting < 4.1.x
databases, and relies on this string being exactly as it is. InnoDB
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";

os_event_wait(slot->event);

if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}

/* When there is user activity, InnoDB will set the event and the
main thread goes back to loop. */

goto loop;
}
分享到:
评论

相关推荐

    mysql-5.5.25a

    MySQL 5.5.25a 是 MySQL 数据库管理系统的一个特定版本,该版本在 MySQL 的发展历史上占有重要的地位。MySQL 是一个开源、免费的关系型数据库管理系统(RDBMS),广泛应用于网页开发、企业数据存储、大数据处理等多...

    mysql-5.5.25a-winx64(安装版).zip

    MySQL 5.5.25a 是 MySQL 数据库管理系统的一个特定版本,专为 Windows 64 位操作系统设计。MySQL 是世界上最受欢迎的开源关系型数据库之一,由 Oracle 公司维护。这个安装版的压缩包“mysql-5.5.25a-winx64.zip”...

    mysql5.5.25 源码阅读笔记

    通过深入阅读MySQL 5.5.25的源码,我们可以了解到数据库系统的底层运作,这对于提升数据库性能调优能力,解决实际问题,以及进行数据库设计和架构优化具有极大的帮助。同时,这也有助于我们理解其他开源数据库系统的...

    mysql-5.5.25安装包

    总的来说,MySQL 5.5.25是一个功能强大且稳定的数据库版本,适用于各种业务场景,尤其适合需要高性能、高并发和事务处理的Web应用程序。配合提供的安装教程,用户可以轻松地在本地环境中部署并运行MySQL服务器。

    mysql-5.5.25-win32.msi

    MySQL是世界上最受欢迎的开源关系型数据库管理系统之一,其版本5.5.25是一个重要的里程...在Windows 32位系统上安装`mysql-5.5.25-win32.msi`,不仅能够享受到这些改进,还能够根据上述步骤和建议进行高效管理和使用。

    mysql-5.5.25-win32

    在安装和使用“mysql-5.5.25-win32”时,用户需要注意配置合适的服务器参数,比如innodb_buffer_pool_size,以最大化性能。同时,定期备份数据库以防止数据丢失,保持系统安全,避免使用即将废弃的功能,如“--safe-...

    apache-TOMCAT-5.5.25

    标题中的"apache-TOMCAT-5.5.25"指的是Apache Tomcat的5.5.25版本。这个版本在发布时是一个稳定且广泛使用的版本,为开发者提供了在Web开发中部署Java应用的服务。 描述中的“tomcat下载 很好用哦”意味着Apache ...

    MySQL-shared-compat-5.5.25a-1.el6.x86_64.rpm

    MySQL-shared-compat-5.5.25a-1.el6.x86_64.rpm

    MySQL-5.5.25a安装包

    MySQL-5.5.25a安装包是一个用于在Windows操作系统上部署MySQL数据库服务器的软件包。MySQL是一款流行的关系型数据库管理系统(RDBMS),由Oracle公司开发和维护,广泛应用于网站开发、企业数据存储、应用程序后端等...

    MySQL-server-5.5.25a-1.el6.x86_64.rpm

    MySQL-server-5.5.25a-1.el6.x86_64.rpm

    MySQL-shared-5.5.25a-1.el6.x86_64.rpm

    MySQL-shared-5.5.25a-1.el6.x86_64.rpm

    MySQL-test-5.5.25a-1.el6.x86_64.rpm

    MySQL-test-5.5.25a-1.el6.x86_64.rpm

    MySQL-client-5.5.25a-1.el6.x86_64.rpm

    MySQL-client-5.5.25a-1.el6.x86_64.rpm 适用于redhat6 centos6 64位系统

    php5.5.25.tar.gz安装包

    本文将详细介绍如何安装和配置PHP 5.5.25的源码包,以及在这个过程中可能遇到的关键知识点。 首先,`php5.5.25.tar.gz` 是一个压缩文件,它包含了PHP 5.5.25的所有源代码。在Linux或类Unix系统上,我们可以使用`tar...

    apache-tomcat-5.5.25-src.tar.gz

    总的来说,`apache-tomcat-5.5.25-src.tar.gz`不仅是一个可部署的服务器,也是一个丰富的学习资源,提供了对Java EE标准实现的洞察,以及对Web服务器架构和工作流程的深入理解。无论是开发者还是运维人员,都能从中...

    MySQL-client-5.5.25a-1.rhel5.x86_64.rpm

    Linux安装MySQL必备,妈妈再也不用担心你找不到资源了,同样也不用担心你不认识英文了。

    MySQL-embedded-5.5.25a-1.el6.x86_64.rpm

    MySQL-embedded-5.5.25a-1.el6.x86_64.rpm

    mysql-5.5.25a.tar.gz

    MySQL是世界上最受欢迎的开源数据库系统之一,而"mysql-5.5.25a.tar.gz"则是一个在Linux环境下使用的MySQL服务器的源码压缩包。这个版本号5.5.25a代表了该软件的一个特定发布迭代,通常包含了一些错误修复、性能提升...

    MySQL-devel-5.5.25a-1.el6.x86_64.rpm

    MySQL-devel-5.5.25a-1.el6.x86_64.rpm

    mysql5.5.25版本安装图解

    MySQL 5.5.25 是一个较早但仍然广泛使用的数据库管理系统版本。这篇图解教程将引导你完成在Windows操作系统上的安装过程。以下是对安装步骤的详细解释: 1. **启动安装**: 首先,你需要双击下载的MySQL安装文件来...

Global site tag (gtag.js) - Google Analytics