May 19, 2013

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

在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, […]