Commit ae4972e4 authored by unknown's avatar unknown

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
parent 1ddcff1b
...@@ -1832,6 +1832,28 @@ buf_get_n_pending_ios(void) ...@@ -1832,6 +1832,28 @@ buf_get_n_pending_ios(void)
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]); + 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. */ Prints info of the buffer i/o. */
......
...@@ -472,6 +472,13 @@ buf_print_io( ...@@ -472,6 +472,13 @@ buf_print_io(
/*=========*/ /*=========*/
char* buf, /* in/out: buffer where to print */ char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */ 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. */ Refreshes the statistics used to print per-second averages. */
......
...@@ -74,6 +74,9 @@ extern ulint srv_lock_wait_timeout; ...@@ -74,6 +74,9 @@ extern ulint srv_lock_wait_timeout;
extern char* srv_file_flush_method_str; extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method; extern ulint srv_unix_file_flush_method;
extern ulint srv_win_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_force_recovery;
extern ulint srv_thread_concurrency; extern ulint srv_thread_concurrency;
......
...@@ -157,6 +157,13 @@ char* srv_file_flush_method_str = NULL; ...@@ -157,6 +157,13 @@ char* srv_file_flush_method_str = NULL;
ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC; ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; 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 /* 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 */ the user from forgetting the innodb_force_recovery keyword to my.cnf */
...@@ -2770,16 +2777,29 @@ srv_master_thread( ...@@ -2770,16 +2777,29 @@ srv_master_thread(
os_event_set(srv_sys->operational); os_event_set(srv_sys->operational);
loop: loop:
/*****************************************************************/
/* ---- When there is database activity by users, we cycle in this
loop */
srv_main_thread_op_info = (char*) "reserving kernel mutex"; srv_main_thread_op_info = (char*) "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written; + buf_pool->n_pages_written;
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
/* Store the user activity counter at the start of this loop */
old_activity_count = srv_activity_count; old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex); 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++) { for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written; + buf_pool->n_pages_written;
...@@ -2797,11 +2817,6 @@ srv_master_thread( ...@@ -2797,11 +2817,6 @@ srv_master_thread(
srv_main_thread_op_info = (char*)""; 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) { if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto background_loop; goto background_loop;
...@@ -2814,7 +2829,7 @@ srv_master_thread( ...@@ -2814,7 +2829,7 @@ srv_master_thread(
srv_main_thread_op_info = (char*)"flushing log"; srv_main_thread_op_info = (char*)"flushing log";
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE); 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 one second sleep, we assume that there is free
disk i/o capacity available, and it makes sense to disk i/o capacity available, and it makes sense to
do an insert buffer merge. */ do an insert buffer merge. */
...@@ -2823,7 +2838,7 @@ srv_master_thread( ...@@ -2823,7 +2838,7 @@ srv_master_thread(
+ log_sys->n_pending_writes; + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written; + 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 = srv_main_thread_op_info =
(char*)"doing insert buffer merge"; (char*)"doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5); ibuf_contract_for_n_pages(TRUE, 5);
...@@ -2834,19 +2849,27 @@ srv_master_thread( ...@@ -2834,19 +2849,27 @@ srv_master_thread(
TRUE); TRUE);
} }
if (srv_activity_count == old_activity_count) { if (buf_get_modified_ratio_pct() >
srv_max_buf_pool_modified_pct) {
if (srv_print_thread_releases) { /* Try to keep the number of modified pages in the
printf("Master thread wakes up!\n"); 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) {
/* There is no user activity at the moment, go to
the background loop */
goto background_loop; goto background_loop;
} }
} }
if (srv_print_thread_releases) { /* ---- We perform the following code approximately once per
printf("Master thread wakes up!\n"); 10 seconds when there is database activity */
}
#ifdef MEM_PERIODIC_CHECK #ifdef MEM_PERIODIC_CHECK
/* Check magic numbers of every allocated mem block once in 10 /* Check magic numbers of every allocated mem block once in 10
...@@ -2855,7 +2878,7 @@ srv_master_thread( ...@@ -2855,7 +2878,7 @@ srv_master_thread(
#endif #endif
/* If there were less than 200 i/os during the 10 second period, /* 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 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_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
...@@ -2906,24 +2929,23 @@ srv_master_thread( ...@@ -2906,24 +2929,23 @@ srv_master_thread(
} }
} }
background_loop: srv_main_thread_op_info = (char*)"flushing buffer pool pages";
/* 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(); /* Flush a few oldest pages to make a new checkpoint younger */
srv_main_thread_op_info = (char*)""; if (buf_get_modified_ratio_pct() > 70) {
srv_main_thread_op_info = (char*)"flushing buffer pool pages"; /* 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 */
/* Flush a few oldest pages to make the checkpoint younger */
if (srv_fast_shutdown && srv_shutdown_state > 0) {
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
ut_dulint_max); ut_dulint_max);
} else { } 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, n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
ut_dulint_max); ut_dulint_max);
} }
...@@ -2937,16 +2959,31 @@ srv_master_thread( ...@@ -2937,16 +2959,31 @@ srv_master_thread(
srv_main_thread_op_info = (char*)"reserving kernel mutex"; srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&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) { if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
goto loop; goto loop;
} }
old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex); 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 /* The server has been quiet for a while: start running background
operations */ 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"; srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) { if (srv_fast_shutdown && srv_shutdown_state > 0) {
...@@ -2981,6 +3018,7 @@ srv_master_thread( ...@@ -2981,6 +3018,7 @@ srv_master_thread(
} }
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
flush_loop:
srv_main_thread_op_info = (char*)"flushing buffer pool pages"; srv_main_thread_op_info = (char*)"flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max); n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
...@@ -3001,6 +3039,14 @@ srv_master_thread( ...@@ -3001,6 +3039,14 @@ srv_master_thread(
log_checkpoint(TRUE, FALSE); 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"; srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
...@@ -3015,15 +3061,24 @@ srv_master_thread( ...@@ -3015,15 +3061,24 @@ srv_master_thread(
log_archive_do(FALSE, &n_bytes_archived); 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 (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_tables_to_drop + n_pages_flushed if (n_tables_to_drop + n_pages_flushed
+ n_bytes_archived != 0) { + 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; goto background_loop;
} }
} else if (n_tables_to_drop + } 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) { + n_bytes_archived != 0) {
/* In a 'slow' shutdown we run purge and the insert buffer
merge to completion */
goto background_loop; goto background_loop;
} }
...@@ -3055,6 +3110,9 @@ srv_master_thread( ...@@ -3055,6 +3110,9 @@ srv_master_thread(
os_event_wait(event); os_event_wait(event);
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
goto loop; goto loop;
#ifndef __WIN__ #ifndef __WIN__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment