diff --git a/mysql-test/suite/sys_vars/r/innodb_idle_flush_pct_basic.result b/mysql-test/suite/sys_vars/r/innodb_idle_flush_pct_basic.result new file mode 100644 index 00000000000..a2c328f38fd --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_idle_flush_pct_basic.result @@ -0,0 +1,77 @@ +SET @start_global_value = @@global.innodb_idle_flush_pct; +SELECT @start_global_value; +@start_global_value +100 +Valid values are between 0 and 100 +select @@global.innodb_idle_flush_pct between 0 and 100; +@@global.innodb_idle_flush_pct between 0 and 100 +1 +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +100 +select @@session.innodb_idle_flush_pct; +ERROR HY000: Variable 'innodb_idle_flush_pct' is a GLOBAL variable +show global variables like 'innodb_idle_flush_pct'; +Variable_name Value +innodb_idle_flush_pct 100 +show session variables like 'innodb_idle_flush_pct'; +Variable_name Value +innodb_idle_flush_pct 100 +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 100 +select * from information_schema.session_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 100 +set global innodb_idle_flush_pct=10; +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +10 +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 10 +select * from information_schema.session_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 10 +set session innodb_idle_flush_pct=1; +ERROR HY000: Variable 'innodb_idle_flush_pct' is a GLOBAL variable and should be set with SET GLOBAL +set global innodb_idle_flush_pct=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_idle_flush_pct' +set global innodb_idle_flush_pct=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_idle_flush_pct' +set global innodb_idle_flush_pct="bar"; +ERROR 42000: Incorrect argument type to variable 'innodb_idle_flush_pct' +set global innodb_idle_flush_pct=-7; +Warnings: +Warning 1292 Truncated incorrect innodb_idle_flush_pct value: '-7' +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +0 +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 0 +set global innodb_idle_flush_pct=106; +Warnings: +Warning 1292 Truncated incorrect innodb_idle_flush_pct value: '106' +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +100 +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_IDLE_FLUSH_PCT 100 +set global innodb_idle_flush_pct=0; +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +0 +set global innodb_idle_flush_pct=100; +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +100 +set global innodb_idle_flush_pct=DEFAULT; +select @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +100 +SET @@global.innodb_idle_flush_pct = @start_global_value; +SELECT @@global.innodb_idle_flush_pct; +@@global.innodb_idle_flush_pct +100 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index f3bc9eead9c..c1823ff7739 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1027,6 +1027,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME INNODB_IDLE_FLUSH_PCT +SESSION_VALUE NULL +GLOBAL_VALUE 100 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 100 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Up to what percentage of dirty pages should be flushed when innodb finds it has spare resources to do so. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 100 +NUMERIC_BLOCK_SIZE 0 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_IO_CAPACITY SESSION_VALUE NULL GLOBAL_VALUE 200 diff --git a/mysql-test/suite/sys_vars/t/innodb_idle_flush_pct_basic.test b/mysql-test/suite/sys_vars/t/innodb_idle_flush_pct_basic.test new file mode 100644 index 00000000000..7175a59e238 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_idle_flush_pct_basic.test @@ -0,0 +1,63 @@ + +# +# 2013-04-01 - Added +# + +--source include/have_innodb.inc + +SET @start_global_value = @@global.innodb_idle_flush_pct; +SELECT @start_global_value; + +# +# exists as global only +# +--echo Valid values are between 0 and 100 +select @@global.innodb_idle_flush_pct between 0 and 100; +select @@global.innodb_idle_flush_pct; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.innodb_idle_flush_pct; +show global variables like 'innodb_idle_flush_pct'; +show session variables like 'innodb_idle_flush_pct'; +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +select * from information_schema.session_variables where variable_name='innodb_idle_flush_pct'; + +# +# show that it's writable +# +set global innodb_idle_flush_pct=10; +select @@global.innodb_idle_flush_pct; +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +select * from information_schema.session_variables where variable_name='innodb_idle_flush_pct'; +--error ER_GLOBAL_VARIABLE +set session innodb_idle_flush_pct=1; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_idle_flush_pct=1.1; +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_idle_flush_pct=1e1; +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_idle_flush_pct="bar"; + +set global innodb_idle_flush_pct=-7; +select @@global.innodb_idle_flush_pct; +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; +set global innodb_idle_flush_pct=106; +select @@global.innodb_idle_flush_pct; +select * from information_schema.global_variables where variable_name='innodb_idle_flush_pct'; + +# +# min/max/DEFAULT values +# +set global innodb_idle_flush_pct=0; +select @@global.innodb_idle_flush_pct; +set global innodb_idle_flush_pct=100; +select @@global.innodb_idle_flush_pct; +set global innodb_idle_flush_pct=DEFAULT; +select @@global.innodb_idle_flush_pct; + + +SET @@global.innodb_idle_flush_pct = @start_global_value; +SELECT @@global.innodb_idle_flush_pct; diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 441fcfb4d94..80b1ce0bb99 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2444,27 +2444,17 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { - /* The page_cleaner skips sleep if the server is - idle and there are no pending IOs in the buffer pool - and there is work to do. */ - if (srv_check_activity(last_activity) - || buf_get_n_pending_read_ios() - || n_flushed == 0) { - page_cleaner_sleep_if_needed(next_loop_time); - } + page_cleaner_sleep_if_needed(next_loop_time); next_loop_time = ut_time_ms() + 1000; if (srv_check_activity(last_activity)) { last_activity = srv_get_activity_count(); - /* Flush pages from end of LRU if required */ - n_flushed = buf_flush_LRU_tail(); - /* Flush pages from flush_list if required */ n_flushed += page_cleaner_flush_pages_if_needed(); - } else { + } else if (srv_idle_flush_pct) { n_flushed = page_cleaner_do_flush_batch( PCT_IO(100), LSN_MAX); @@ -2477,6 +2467,9 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( n_flushed); } } + + /* Flush pages from end of LRU if required */ + buf_flush_LRU_tail(); } ut_ad(srv_shutdown_state > 0); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ee06401be24..ced6faba79b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -17891,6 +17891,13 @@ static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity, SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100, SRV_MAX_IO_CAPACITY_LIMIT, 0); +static MYSQL_SYSVAR_ULONG(idle_flush_pct, + srv_idle_flush_pct, + PLUGIN_VAR_RQCMDARG, + "Up to what percentage of dirty pages should be flushed when innodb " + "finds it has spare resources to do so.", + NULL, NULL, 100, 0, 100, 0); + #ifdef UNIV_DEBUG static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now, PLUGIN_VAR_OPCMDARG, @@ -18920,6 +18927,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(read_only), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(io_capacity_max), + MYSQL_SYSVAR(idle_flush_pct), MYSQL_SYSVAR(monitor_enable), MYSQL_SYSVAR(monitor_disable), MYSQL_SYSVAR(monitor_reset), diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 7ba69736271..e3ac49c50ac 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -359,6 +359,8 @@ extern double srv_defragment_fill_factor; extern uint srv_defragment_frequency; extern ulonglong srv_defragment_interval; +extern ulint srv_idle_flush_pct; + /* Number of IO operations per second the server can do */ extern ulong srv_io_capacity; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index ca5c22d8ee4..5dfb38b53c7 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -257,6 +257,8 @@ UNIV_INTERN ulint srv_buf_pool_curr_size = 0; UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX; UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX; +UNIV_INTERN ulint srv_idle_flush_pct = 100; + /* This parameter is deprecated. Use srv_n_io_[read|write]_threads instead. */ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX; diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index ac614823bc1..4b160aea988 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -2736,14 +2736,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( srv_current_thread_priority = srv_cleaner_thread_priority; - /* The page_cleaner skips sleep if the server is - idle and there are no pending IOs in the buffer pool - and there is work to do. */ - if (srv_check_activity(last_activity) - || buf_get_n_pending_read_ios() - || n_flushed == 0) { - page_cleaner_sleep_if_needed(next_loop_time); - } + page_cleaner_sleep_if_needed(next_loop_time); page_cleaner_sleep_time = page_cleaner_adapt_flush_sleep_time(); @@ -2761,8 +2754,8 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( } /* Flush pages from flush_list if required */ - n_flushed += page_cleaner_flush_pages_if_needed(); - } else { + page_cleaner_flush_pages_if_needed(); + } else if (srv_idle_flush_pct) { n_flushed = page_cleaner_do_flush_batch( PCT_IO(100), LSN_MAX); @@ -2775,6 +2768,9 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)( n_flushed); } } + + /* Flush pages from end of LRU if required */ + buf_flush_LRU_tail(); } ut_ad(srv_shutdown_state > 0); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 43349146c14..93563b16c13 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -18970,6 +18970,13 @@ static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity, SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100, SRV_MAX_IO_CAPACITY_LIMIT, 0); +static MYSQL_SYSVAR_ULONG(idle_flush_pct, + srv_idle_flush_pct, + PLUGIN_VAR_RQCMDARG, + "Up to what percentage of dirty pages should be flushed when innodb " + "finds it has spare resources to do so.", + NULL, NULL, 100, 0, 100, 0); + #ifdef UNIV_DEBUG static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now, PLUGIN_VAR_OPCMDARG, @@ -20224,6 +20231,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(read_only), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(io_capacity_max), + MYSQL_SYSVAR(idle_flush_pct), MYSQL_SYSVAR(monitor_enable), MYSQL_SYSVAR(monitor_disable), MYSQL_SYSVAR(monitor_reset), diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 17c67ada04b..2825e37ba86 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -424,6 +424,8 @@ extern double srv_defragment_fill_factor; extern uint srv_defragment_frequency; extern ulonglong srv_defragment_interval; +extern ulint srv_idle_flush_pct; + /* Number of IO operations per second the server can do */ extern ulong srv_io_capacity; diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 16df97edd64..a6035bdaa6c 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -341,6 +341,8 @@ UNIV_INTERN ulong srv_cleaner_lsn_age_factor UNIV_INTERN ulong srv_empty_free_list_algorithm = SRV_EMPTY_FREE_LIST_BACKOFF; +UNIV_INTERN ulint srv_idle_flush_pct = 100; + /* This parameter is deprecated. Use srv_n_io_[read|write]_threads instead. */ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;