這部分内容是從http://mysqllover.com/?p=512 剝離出來,原文中為了保持整潔,将這些内容删除。
有以下幾個參數會影響到page cleaner的行為:
innodb_lru_scan_depth
innodb_adaptive_flushing_lwm
innodb_max_dirty_pages_pct_lwm
innodb_io_capacity_max
innodb_flushing_avg_loops
在函數page_cleaner_flush_pages_if_needed中會确定三個影響刷髒頁行為的變量
1. 根據redo log計算比例(pct_for_lsn),當小于innodb_adaptive_flushing_lwm時,pct_for_lsn值為0,當小于異步刷redo的比例(log_sys->max_modified_age_async)時且關閉選項innodb_adaptive_flushing時,pct_for_lsn也為0,否則,計算:
((innodb_io_capacity_max/innodb_io_capacity)
*(lsn_age_factor * sqrt((double)lsn_age_factor)))/7.5
其中lsn_age_factor為目前的(redo比例*100)/max_modified_age_async
2. 根據髒頁計算比例(pct_for_dirty),當innodb_max_dirty_pages_pct_lwm設定為0時,和以前的行為類似,如果髒頁比例大于innodb_max_dirty_pages_pct時,pct_for_dirty設定為100,否則如果髒頁比大于innodb_max_dirty_pages_pct_lwm,pct_for_dirty值為
(dirty_pct * 100)/( innodb_max_dirty_pages_pct+1)
3. 最近innodb_flushing_avg_loops次平均刷髒頁的數量,同時還考慮上次統計時候的平均數量,再除以2
avg_page_rate= ((sum_pages / srv_flushing_avg_loops) + avg_page_rate) / 2
另外也會計算lsn的重新整理速率
lsn_rate= (cur_lsn – prev_lsn) / srv_flushing_avg_loops;
lsn_avg_rate= (lsn_avg_rate + lsn_rate) / 2;
然後根據上述兩個值計算要重新整理的page數:
pct_total = ut_max(pct_for_dirty, pct_for_lsn);
n_pages = (pct_io(pct_total) + avg_page_rate) / 2;
if (n_pages > srv_max_io_capacity) {
n_pages =srv_max_io_capacity;
}
除了髒頁的數量外,還要确定一個lsn下限值(lsn_limit),oldest_modification小于lsn_limit的block需要被重新整理掉,其計算方式也受參數innodb_flushing_avg_loops影響:
每innodb_flushing_avg_loops次循環,計算
lsn_rate = (cur_lsn – prev_lsn) /srv_flushing_avg_loops;
lsn_avg_rate = (lsn_avg_rate + lsn_rate) / 2;
lsn_avg_rate表示lsn最近的平均推進速率
然後計算lsn_limit:
if (last_pages && cur_lsn – last_lsn >lsn_avg_rate / 2) {
age_factor= prev_pages / last_pages;
lsn_limit = oldest_lsn + lsn_avg_rate * (age_factor +1)
prev_pages表示上一次重新整理時,試圖刷的page數,last_pages表示上次實際重新整理的page數,age_factor總是大于等于1的。
oldest_lsn表示目前bp中的最老lsn.
在确定了需要重新整理的page數及哪些page需要被重新整理後,就可以調用函數page_cleaner_do_flush_batch-> buf_flush_list做實際的操作了。
innodb_flush_log_at_timeout #每隔這麼多秒刷一次日志,隻有在innodb_flush_log_at_trx_commit=2時才生效.在master線程中判斷,見函數srv_sync_log_buffer_in_background,在兩個函數中會調用:
1.srv_master_do_active_tasks
2.srv_master_do_idle_tasks
從命名也可以了解,master線程在系統繁忙及空閑時,都會去做判斷。在5.6的master線程函數srv_master_thread中,每sleep 1秒,會根據目前的系統負載是否繁忙去調用上面這兩個函數,相比之前的函數,master線程函數要清爽很多了。每隔innodb_flush_log_at_timeout秒,會調用log_buffer_sync_in_background(true)去刷日志。