[MySQL 5.6] Innodb后台线程之master线程

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
日志服务 SLS,月写入数据量 50GB 1个月
简介:
在MySQL 5.6中,master线程的工作已经被大大减轻,类似purge, page clean都分配给独立的后台线程来进行。那么现在master线程还需要干啥活儿呢。以下就是本文需要介绍的部分

简单的看看代码,函数入口不变,依旧是srv_master_thread,但相对5.5的代码,这里已经非常非常精简了。
概括的说,master线程干这么几件事儿:
A. 每sleep 1秒钟
检查最近1秒内是否有活跃事件,这是一个全局计数器,在几个地方会被递增(通过函数srv_inc_activity_count):
1.srv_active_wake_master_thread—> 实际上在5.6里这里只剩下计数器的功能了,因为除非是以force recovery 启动,或者被shutdown了,否则不会进入suspend状态
2.srv_wake_master_thread—> 在DROP/TRUNCATE TABLE时会调用到,实际上 ,在5.6的代码里,master线程大多是在sleep的状态,并不需要去做wake up的动作(report了一个bug:http://bugs.mysql.com/bug.php?id=69270
3.row_undo_step->事务回滚时
例如事务提交/prepare时(innobase_commit->srv_active_wake_master_thread) ,事务回滚时,一个简单的查询都会引起计数器增加,从而让Master线程判定现在系统正忙.
A.1如果认定现在系统正忙,则调用函数srv_master_do_active_tasks,做如下工作:
1.log_free_check
总会检查redo中是否有足够的空间,以确定是否做flush或者做checkpoint,通常情况下,用户线程在写redo日志之前也会无条件调用该函数。
这里会先在无加锁的情况下,检查log_sys->check_flush_or_checkpoint是否为TRUE,如果为TRUE,则调用log_check_margins(),否则直接返回。
check_flush_or_checkpoint在函数log_close中被设置,backtrace如下:
      mtr_commit->mtr_log_reserve_and_write->log_close()
在每次将一个mtr日志写到buffer后,总会调用log_close()函数,注意,该函数是持有log_sys->mutex锁的
有以下几种情况会去设置check_flush_or_checkpoint为TRUE:
    • log_sys->buf_free > log_sys->max_buf_free
    • log_sys->lsn-buf_pool_get_oldest_modification() >log_sys->max_modified_age_sync
    • log_sys->lsn-log_sys->last_checkpoint_lsn > log_sys->max_checkpoint_age_async
TODO: mtr的组织,如何提交,以及redo 日志在内存中的控制
log_free_check会调用log_check_margins做两件事:
1)调用log_flush_margin:首先确认log->buf_free 是否大于 log->max_buf_free,如果是,则需要将日志写到文件,到当前lsn(log_write_up_to(lsn, LOG_NO_WAIT, FALSE))。如果已经有别的线程在干这活儿,则啥也不干,返回
2)调用log_checkpoint_margin,判断是否达到redo的同步刷脏点,或者异步/同步checkpoint点,决定是否刷脏(log_preflush_pool_modified_pages)及做checkpoint(log_checkpoint)
3)如果log_sys->check_flush_or_checkpoint依然为TRUE,则回到1)继续。


2.ibuf_contract_in_background(0, FALSE);
做ibuf merge, 正常情况下,每次处理innodb_io_capacity*0.05个page,
但如果ibuf->size > ibuf->max_size / 2,则处理:
n_pages = innodb_io_capacity   *   { [((ibuf->size – ibuf->max_size / 2)*100)/(ibuf->max_size + 1)]/100 }
这种情况说明change buffer太多了,需要合并更多的page
3.srv_sync_log_buffer_in_background();
如果需要的话,sync日志到磁盘
master线程通过该函数确保每隔一段时间,刷一次redo日志到磁盘log_buffer_sync_in_background(TRUE)->log_write_up_to(log_sys->lsn, LOG_NO_WAIT, TRUE)
时间间隔由innodb_flush_log_at_timeout来控制,单位为秒。
根据文档的解释,innodb_flush_log_at_timeout只有在innodb_flush_log_at_trx_commit值为2时才生效,但事实上,不管inndob_flush_log_at_trx_commit设为何值,都会调用log_buffer_sync_in_background
TODO:需要检查,如果innodb_flush_log_at_trx_commit设为1时,是否还需要调用srv_sync_log_buffer_in_background()函数
4.如果打开了MEM_PERIODIC_CHECK宏(默认关闭),则每隔13秒,检查是否出现内存损坏(mem_validate_all_blocks)
5.每隔47秒(SRV_MASTER_DICT_LRU_INTERVAL)检查一次dict cache。
srv_master_evict_from_table_cache(50)
需要持有dict_operation_lock的x锁,以及dict_sys->mutex
dict_make_room_in_cache :最大允许的table cache大小由table_definition_cache来决定
> 如果当前dict_sys->table_LRU的长度尚小于table_definition_cache,无需检测,直接返回
>否则,从table_LRU尾部开始,对于可以驱逐的表(dict_table_remove_from_cache_low),从dict cache中移除(dict_table_remove_from_cache_low),直到检测长度超过pct_check(这里是50%)或者dict cache长度<=table_definition_cache停止扫描
满足如下条件的表可以被从dict cache中驱逐:
1.当前没有被任何事务引用(table->n_ref_count = 0 )
2.该表上没有表锁或和录锁(table->locks) ==  0  &&  table->n_rec_locks == 0)
3.表上的索引没有被adaptive hash index引用(index->search_info->ref_count 为0)
这也是5.6的一点优化,主要是防止数据词典过大导致太大的内存消耗.如果内存对你而言不是问题,那就尽量调大table_definition_cache吧。
6.每隔7秒(SRV_MASTER_CHECKPOINT_INTERVAL)做一次新的checkpoint
log_checkpoint(TRUE, FALSE); 
A.2如果认定现在系统正处于空闲,则调用函数srv_master_do_idle_tasks
1.检查redo log_free_check();
2.做一次ibuf merge  
ibuf_contract_in_background(0, TRUE);
3.检查dict cache ,srv_master_evict_from_table_cache(100);
4.刷日志(srv_sync_log_buffer_in_background)
5.做一次新的checkpoint .log_checkpoint
idle 和 active的时候,所做的事情几乎是一样的,不同的是,在active状态下,每47秒才检查dict cache,每7秒才做一次check point 
因此在idle状态下,master线程可能会更加繁忙
B.在关闭实例时
调用srv_master_do_shutdown_tasks
1.log_free_check()
2.ibuf_contract_in_background(0, TRUE)
3.srv_sync_log_buffer_in_background()
4.log_checkpoint(TRUE, FALSE);

5.                srv_shutdown_print_master_pending(

                        last_print_time, n_tables_to_drop, n_bytes_merged);

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
24天前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
29天前
|
存储 SQL 关系型数据库
【MySQL技术内幕】6.3-InnoDB中的锁
【MySQL技术内幕】6.3-InnoDB中的锁
154 57
|
19天前
|
存储 关系型数据库 MySQL
关系型数据库mysql的InnoDB
【6月更文挑战第17天】
20 3
|
29天前
|
存储 算法 关系型数据库
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
20 1
|
29天前
|
存储 算法 关系型数据库
【MySQL技术内幕】4.4-InnoDB数据页结构
【MySQL技术内幕】4.4-InnoDB数据页结构
25 1
|
16天前
|
关系型数据库 MySQL 调度
深入理解MySQL InnoDB线程模型
深入理解MySQL InnoDB线程模型
|
16天前
|
存储 关系型数据库 MySQL
mysql的InnoDB引擎实现ACID特性的原理
mysql的InnoDB引擎实现ACID特性的原理
|
29天前
|
存储 关系型数据库 MySQL
【MySQL技术内幕】5.1-InnoDB存储引擎索引概述
【MySQL技术内幕】5.1-InnoDB存储引擎索引概述
31 0
|
29天前
|
存储 SQL 关系型数据库
【MySQL技术内幕】4.2-InnoDB行记录格式
【MySQL技术内幕】4.2-InnoDB行记录格式
21 0
|
2月前
|
存储 监控 关系型数据库
MySQL 参数innodb_read_io_threads
`innodb_read_io_threads` 是 MySQL 数据库中 InnoDB 存储引擎的一个配置参数,它用于指定后台线程池中用于处理读取 I/O 请求的线程数量。InnoDB 存储引擎负责管理数据库的物理存储和检索,是 MySQL 最常用的存储引擎之一。 ### 参数说明 - **名称**: `innodb_read_io_threads` - **默认值**: 4 - **范围**: 1 到 64 - **动态修改**: 不能动态修改(需要重启服务器) - **适用版本**: MySQL 5.6 及以上版本 ### 作用 `innodb_read_io_threads`
199 1