From 1d64ab5e4705207196d6ff34f866a1070d49f108 Mon Sep 17 00:00:00 2001 From: unknown <heikki@hundin.mysql.fi> Date: Sat, 3 May 2003 19:44:46 +0300 Subject: [PATCH] buf0buf.c, srv0srv.h, buf0buf.h, srv0srv.c: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker innobase/srv/srv0srv.c: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker innobase/include/buf0buf.h: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker innobase/include/srv0srv.h: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker innobase/buf/buf0buf.c: Clean up the working of the main thread; add a tunable parameter srv_max_buf_pool_modified_pct which can be used to make the flush phase in shutdown quicker --- innobase/buf/buf0buf.c | 22 +++++++ innobase/include/buf0buf.h | 7 +++ innobase/include/srv0srv.h | 3 + innobase/srv/srv0srv.c | 114 ++++++++++++++++++++++++++++--------- 4 files changed, 118 insertions(+), 28 deletions(-) diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 42799da9d7..944a5ef60d 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -1832,6 +1832,28 @@ buf_get_n_pending_ios(void) + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); } +/************************************************************************* +Returns the ratio in percents of modified pages in the buffer pool / +database pages in the buffer pool. */ + +ulint +buf_get_modified_ratio_pct(void) +/*============================*/ +{ + ulint ratio; + + mutex_enter(&(buf_pool->mutex)); + + ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list)) + / (1 + UT_LIST_GET_LEN(buf_pool->LRU)); + + /* 1 + is there to avoid division by zero */ + + mutex_exit(&(buf_pool->mutex)); + + return(ratio); +} + /************************************************************************* Prints info of the buffer i/o. */ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 395f88a2c7..e4d3671586 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -472,6 +472,13 @@ buf_print_io( /*=========*/ char* buf, /* in/out: buffer where to print */ char* buf_end);/* in: buffer end */ +/************************************************************************* +Returns the ratio in percents of modified pages in the buffer pool / +database pages in the buffer pool. */ + +ulint +buf_get_modified_ratio_pct(void); +/*============================*/ /************************************************************************** Refreshes the statistics used to print per-second averages. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index ad6f71f7a3..8355496762 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -74,6 +74,9 @@ extern ulint srv_lock_wait_timeout; extern char* srv_file_flush_method_str; extern ulint srv_unix_file_flush_method; extern ulint srv_win_file_flush_method; + +extern ulint srv_max_dirty_pages_pct; + extern ulint srv_force_recovery; extern ulint srv_thread_concurrency; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 07df708e5f..97841056b1 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -157,6 +157,13 @@ char* srv_file_flush_method_str = NULL; ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; +/* The InnoDB main thread tries to keep the ratio of modified pages +in the buffer pool to all database pages in the buffer pool smaller than +the following number. But it is not guaranteed that the value stays below +that during a time of heavy update/insert activity. */ + +ulint srv_max_buf_pool_modified_pct = 30; + /* If the following is != 0 we do not allow inserts etc. This protects the user from forgetting the innodb_force_recovery keyword to my.cnf */ @@ -2770,16 +2777,29 @@ srv_master_thread( os_event_set(srv_sys->operational); loop: + /*****************************************************************/ + /* ---- When there is database activity by users, we cycle in this + loop */ + srv_main_thread_op_info = (char*) "reserving kernel mutex"; n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->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 */ + for (i = 0; i < 10; i++) { n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; @@ -2797,11 +2817,6 @@ loop: srv_main_thread_op_info = (char*)""; - if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) { - - goto suspend_thread; - } - if (srv_fast_shutdown && srv_shutdown_state > 0) { goto background_loop; @@ -2814,7 +2829,7 @@ loop: srv_main_thread_op_info = (char*)"flushing log"; log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); - /* If there were less than 10 i/os during the + /* If there were less than 5 i/os during the one second sleep, we assume that there is free disk i/o capacity available, and it makes sense to do an insert buffer merge. */ @@ -2823,7 +2838,7 @@ loop: + log_sys->n_pending_writes; n_ios = log_sys->n_log_ios + buf_pool->n_pages_read + buf_pool->n_pages_written; - if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) { + if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) { srv_main_thread_op_info = (char*)"doing insert buffer merge"; ibuf_contract_for_n_pages(TRUE, 5); @@ -2834,19 +2849,27 @@ loop: TRUE); } + if (buf_get_modified_ratio_pct() > + srv_max_buf_pool_modified_pct) { + + /* Try to keep the number of modified pages in the + buffer pool under the limit wished by the user */ + + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, + ut_dulint_max); + } + if (srv_activity_count == old_activity_count) { - if (srv_print_thread_releases) { - printf("Master thread wakes up!\n"); - } + /* There is no user activity at the moment, go to + the background loop */ goto background_loop; } } - if (srv_print_thread_releases) { - printf("Master thread wakes up!\n"); - } + /* ---- We perform the following code approximately once per + 10 seconds when there is database activity */ #ifdef MEM_PERIODIC_CHECK /* Check magic numbers of every allocated mem block once in 10 @@ -2855,7 +2878,7 @@ loop: #endif /* If there were less than 200 i/os during the 10 second period, we assume that there is free disk i/o capacity available, and it - makes sense to do a buffer pool flush. */ + makes sense to flush 100 pages. */ n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes; n_ios = log_sys->n_log_ios + buf_pool->n_pages_read @@ -2905,25 +2928,24 @@ loop: last_flush_time = current_time; } } - -background_loop: - /* In this loop we run background operations when the server - is quiet and we also come here about once in 10 seconds */ - - srv_main_thread_op_info = (char*)"doing background drop tables"; - - n_tables_to_drop = row_drop_tables_for_mysql_in_background(); - - srv_main_thread_op_info = (char*)""; srv_main_thread_op_info = (char*)"flushing buffer pool pages"; - /* Flush a few oldest pages to make the checkpoint younger */ + /* Flush a few oldest pages to make a new checkpoint younger */ + + if (buf_get_modified_ratio_pct() > 70) { + + /* If there are lots of modified pages in the buffer pool + (> 70 %), we assume we can afford reserving the disk(s) for + the time it requires to flush 100 pages */ - if (srv_fast_shutdown && srv_shutdown_state > 0) { n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); } else { + /* Otherwise, we only flush a small number of pages so that + we do not unnecessarily use much disk i/o capacity from + other work */ + n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max); } @@ -2937,16 +2959,31 @@ background_loop: srv_main_thread_op_info = (char*)"reserving kernel mutex"; mutex_enter(&kernel_mutex); + + /* ---- When there is database activity, we jump from here back to + the start of loop */ + if (srv_activity_count != old_activity_count) { mutex_exit(&kernel_mutex); goto loop; } - old_activity_count = srv_activity_count; + mutex_exit(&kernel_mutex); + /* If the database is quiet, we enter the background loop */ + + /*****************************************************************/ +background_loop: + /* ---- In this loop we run background operations when the server + is quiet from user activity */ + /* The server has been quiet for a while: start running background operations */ + srv_main_thread_op_info = (char*)"doing background drop tables"; + + n_tables_to_drop = row_drop_tables_for_mysql_in_background(); + srv_main_thread_op_info = (char*)"purging"; if (srv_fast_shutdown && srv_shutdown_state > 0) { @@ -2981,6 +3018,7 @@ background_loop: } mutex_exit(&kernel_mutex); +flush_loop: srv_main_thread_op_info = (char*)"flushing buffer pool pages"; n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); @@ -3001,6 +3039,14 @@ background_loop: log_checkpoint(TRUE, FALSE); + if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) { + + /* Try to keep the number of modified pages in the + buffer pool under the limit wished by the user */ + + goto flush_loop; + } + srv_main_thread_op_info = (char*)"reserving kernel mutex"; mutex_enter(&kernel_mutex); @@ -3015,15 +3061,24 @@ background_loop: log_archive_do(FALSE, &n_bytes_archived); + /* Keep looping in the background loop if still work to do */ + if (srv_fast_shutdown && srv_shutdown_state > 0) { if (n_tables_to_drop + n_pages_flushed + n_bytes_archived != 0) { + /* If we are doing a fast shutdown (= the default) + we do not do purge or insert buffer merge. But we + flush the buffer pool completely to disk. */ + goto background_loop; } } else if (n_tables_to_drop + - n_pages_purged + n_bytes_merged + n_pages_flushed + n_pages_purged + n_bytes_merged + n_pages_flushed + n_bytes_archived != 0) { + /* In a 'slow' shutdown we run purge and the insert buffer + merge to completion */ + goto background_loop; } @@ -3055,6 +3110,9 @@ suspend_thread: os_event_wait(event); + /* When there is user activity, InnoDB will set the event and the main + thread goes back to loop: */ + goto loop; #ifndef __WIN__ -- 2.30.9