您的位置:首页 > 其它

Innodb后台线程之master线程刷新时间

2017-03-29 16:36 113 查看
在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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: