diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2020-03-14 20:52:17 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2020-03-14 22:48:10 +0100 |
commit | 39d0675652eff6affbe35520e7599842dbc53863 (patch) | |
tree | c5d7beb439bcedca027a8540ac5367abd1fbf54c | |
parent | 5754ea2eca0ffa191b4be46fdebf2d49c438f151 (diff) | |
download | mariadb-git-10.5-wlad.tar.gz |
dynamic nr of Innodb io threads10.5-wlad
-rw-r--r-- | mysql-test/suite/sys_vars/r/innodb_file_io_threads_basic.result | 6 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result | 14 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result | 6 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test | 7 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test | 12 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test | 8 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 36 | ||||
-rw-r--r-- | storage/innobase/os/os0file.cc | 82 | ||||
-rw-r--r-- | tpool/tpool.h | 14 | ||||
-rw-r--r-- | tpool/tpool_structs.h | 34 |
10 files changed, 181 insertions, 38 deletions
diff --git a/mysql-test/suite/sys_vars/r/innodb_file_io_threads_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_io_threads_basic.result index 5ef7e1099e0..0442cee0551 100644 --- a/mysql-test/suite/sys_vars/r/innodb_file_io_threads_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_file_io_threads_basic.result @@ -8,16 +8,10 @@ COUNT(@@GLOBAL.innodb_write_io_threads) 1 1 Expected '#---------------------BS_STVARS_027_02----------------------#' -SET @@GLOBAL.innodb_read_io_threads=1; -ERROR HY000: Variable 'innodb_read_io_threads' is a read only variable -Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_read_io_threads); COUNT(@@GLOBAL.innodb_read_io_threads) 1 1 Expected -SET @@GLOBAL.innodb_write_io_threads=1; -ERROR HY000: Variable 'innodb_write_io_threads' is a read only variable -Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_write_io_threads); COUNT(@@GLOBAL.innodb_write_io_threads) 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result b/mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result index f43fa81c0d0..6ec897cea02 100644 --- a/mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result @@ -15,7 +15,15 @@ INNODB_READ_IO_THREADS 2 select * from information_schema.session_variables where variable_name='innodb_read_io_threads'; VARIABLE_NAME VARIABLE_VALUE INNODB_READ_IO_THREADS 2 -set global innodb_read_io_threads=1; -ERROR HY000: Variable 'innodb_read_io_threads' is a read only variable +select @@innodb_read_io_threads into @n; +set global innodb_read_io_threads = 1; +select @@innodb_read_io_threads; +@@innodb_read_io_threads +1 +set global innodb_read_io_threads=64; +select @@innodb_read_io_threads; +@@innodb_read_io_threads +64 set session innodb_read_io_threads=1; -ERROR HY000: Variable 'innodb_read_io_threads' is a read only variable +ERROR HY000: Variable 'innodb_read_io_threads' is a GLOBAL variable and should be set with SET GLOBAL +set global innodb_read_io_threads=@n; diff --git a/mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result b/mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result index a363f4292dd..c10dac084ca 100644 --- a/mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result @@ -15,7 +15,7 @@ INNODB_WRITE_IO_THREADS 2 select * from information_schema.session_variables where variable_name='innodb_write_io_threads'; VARIABLE_NAME VARIABLE_VALUE INNODB_WRITE_IO_THREADS 2 +select @@innodb_write_io_threads into @n; set global innodb_write_io_threads=1; -ERROR HY000: Variable 'innodb_write_io_threads' is a read only variable -set session innodb_write_io_threads=1; -ERROR HY000: Variable 'innodb_write_io_threads' is a read only variable +set global innodb_write_io_threads=64; +set global innodb_write_io_threads=@n; diff --git a/mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test b/mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test index c701c2ee171..802d7e836e7 100644 --- a/mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test @@ -39,17 +39,10 @@ SELECT COUNT(@@GLOBAL.innodb_write_io_threads); # Check if Value can set # #################################################################### ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SET @@GLOBAL.innodb_read_io_threads=1; ---echo Expected error 'Read only variable' SELECT COUNT(@@GLOBAL.innodb_read_io_threads); --echo 1 Expected ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SET @@GLOBAL.innodb_write_io_threads=1; ---echo Expected error 'Read only variable' - SELECT COUNT(@@GLOBAL.innodb_write_io_threads); --echo 1 Expected diff --git a/mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test b/mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test index c4c49d5bb20..610b2ae52c2 100644 --- a/mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test @@ -19,10 +19,14 @@ select * from information_schema.session_variables where variable_name='innodb_r --enable_warnings # -# show that it's read-only +# show that it's not read-only # ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global innodb_read_io_threads=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@innodb_read_io_threads into @n; +set global innodb_read_io_threads = 1; +select @@innodb_read_io_threads; +set global innodb_read_io_threads=64; +select @@innodb_read_io_threads; +--error ER_GLOBAL_VARIABLE set session innodb_read_io_threads=1; +set global innodb_read_io_threads=@n; diff --git a/mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test b/mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test index d9556af37d1..c9c5184d662 100644 --- a/mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test @@ -19,10 +19,10 @@ select * from information_schema.session_variables where variable_name='innodb_w --enable_warnings # -# show that it's read-only +# show that it's not read-only # ---error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@innodb_write_io_threads into @n; set global innodb_write_io_threads=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set session innodb_write_io_threads=1; +set global innodb_write_io_threads=64; +set global innodb_write_io_threads=@n; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a2849c18aa7..6efd55566e7 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19683,15 +19683,43 @@ static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only, "Only optimize the Fulltext index of the table", NULL, NULL, FALSE); +extern int os_aio_resize(ulint n_reader_threads, ulint n_writer_threads); +static void innodb_update_io_thread_count(THD *thd,ulint n_read, ulint n_write) +{ + int res = os_aio_resize(n_read, n_write); + if (res) + { +#ifndef __linux__ + ut_ad(0); +#else + ut_a(srv_use_native_aio); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "Could reserve max. number of concurrent ios." + "Increase the /proc/sys/fs/aio-max-nr to fix."); +#endif + } +} + +static void innodb_read_io_threads_update(THD* thd, struct st_mysql_sys_var*, void*, const void* save) +{ + innodb_update_io_thread_count(thd, *(ulong*)save, srv_n_write_io_threads); +} + +static void innodb_write_io_threads_update(THD* thd, struct st_mysql_sys_var*, void*, const void* save) +{ + innodb_update_io_thread_count(thd, srv_n_read_io_threads, *(ulong*)save); +} + static MYSQL_SYSVAR_ULONG(read_io_threads, srv_n_read_io_threads, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + PLUGIN_VAR_RQCMDARG, "Number of background read I/O threads in InnoDB.", - NULL, NULL, 4, 1, 64, 0); + NULL, innodb_read_io_threads_update , 4, 1, 64, 0); static MYSQL_SYSVAR_ULONG(write_io_threads, srv_n_write_io_threads, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + PLUGIN_VAR_RQCMDARG, "Number of background write I/O threads in InnoDB.", - NULL, NULL, 4, 1, 64, 0); + NULL, innodb_write_io_threads_update, 4, 1, 64, 0); static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index b46caac721e..a51f050ed96 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -109,6 +109,11 @@ public: } /* Wait for completions of all AIO operations */ + void wait(std::unique_lock<std::mutex> &lk) + { + m_cache.wait(lk); + } + void wait() { m_cache.wait(); @@ -128,6 +133,24 @@ public: { wait(); } + + std::mutex& mutex() + { + return m_cache.mutex(); + } + + void resize(int max_submitted_io, int max_callback_concurrency, std::unique_lock<std::mutex> &lk) + { + ut_a(lk.owns_lock()); + m_cache.resize(max_submitted_io); + m_group.set_max_tasks(max_callback_concurrency); + m_max_aio = max_submitted_io; + } + + tpool::task_group& task_group() + { + return m_group; + } }; static io_slots *read_slots; @@ -4029,7 +4052,6 @@ static bool is_linux_native_aio_supported() #endif - bool os_aio_init(ulint n_reader_threads, ulint n_writer_threads, ulint) { int max_write_events= int(n_writer_threads * OS_AIO_N_PENDING_IOS_PER_THREAD); @@ -4058,6 +4080,64 @@ bool os_aio_init(ulint n_reader_threads, ulint n_writer_threads, ulint) return true; } +/** +Change reader or writer thread parameter on a running server. +This includes resizing the io slots, as we calculate +number of outstanding IOs based on the these variables. + +It is trickier with when Linux AIO is involved (io_context +needs to be recreated to account for different number of +max_events). With Linux AIO, depending on fs-max-aio number +and user and system wide max-aio limitation, this can fail. + +Otherwise, we just resize the slots, and allow for +more concurrent threads via thread_group setting. + +@param[in] n_reader_threads - max number of concurrently + executing read callbacks +@param[in] n_writer_thread - max number of cuncurrently + executing write callbacks +@return 0 for success, !=0 for error. +*/ +int os_aio_resize(ulint n_reader_threads, ulint n_writer_threads) +{ + /* Lock the slots, and wait until all current IOs finish. + */ + std::unique_lock<std::mutex> lk_read(read_slots->mutex()); + std::unique_lock<std::mutex> lk_write(write_slots->mutex()); + std::unique_lock<std::mutex> lk_ibuf(ibuf_slots->mutex()); + + read_slots->wait(lk_read); + write_slots->wait(lk_write); + ibuf_slots->wait(lk_ibuf); + + /* Now, all IOs have finished and no new ones can start, due to locks. */ + int max_read_events = int(n_reader_threads * OS_AIO_N_PENDING_IOS_PER_THREAD); + int max_write_events = int(n_writer_threads * OS_AIO_N_PENDING_IOS_PER_THREAD); + int max_ibuf_events = 1 * OS_AIO_N_PENDING_IOS_PER_THREAD; + int max_events = max_read_events + max_write_events + max_ibuf_events; + + /** Do the Linux AIO dance (this will try to create a new + io context with changed max_events ,etc*/ + + int ret = srv_thread_pool->reconfigure_aio(srv_use_native_aio, max_events); + + if (ret) + { + /** Do the best effort. We can't change the parallel io number, + but we still can adjust the number of concurrent completion handlers.*/ + read_slots->task_group().set_max_tasks((int)n_reader_threads); + write_slots->task_group().set_max_tasks((int)n_writer_threads); + return ret; + } + + /* Allocation succeeded, resize the slots*/ + read_slots->resize(max_read_events, (int)n_reader_threads, lk_read); + write_slots->resize(max_write_events, (int)n_writer_threads, lk_write); + + return 0; +} + void os_aio_free() { srv_thread_pool->disable_aio(); diff --git a/tpool/tpool.h b/tpool/tpool.h index ae9baf236b0..d1def554e9a 100644 --- a/tpool/tpool.h +++ b/tpool/tpool.h @@ -224,6 +224,20 @@ public: m_aio.reset(create_simulated_aio(this)); return !m_aio ? -1 : 0; } + + int reconfigure_aio(bool use_native_aio, int max_io) + { + assert(m_aio); + if (use_native_aio) + { + auto new_aio = create_native_aio(max_io); + if (!new_aio) + return -1; + m_aio.reset(new_aio); + } + return 0; + } + void disable_aio() { m_aio.reset(); diff --git a/tpool/tpool_structs.h b/tpool/tpool_structs.h index 7b0fb857695..08c17540f69 100644 --- a/tpool/tpool_structs.h +++ b/tpool/tpool_structs.h @@ -94,6 +94,10 @@ public: return ret; } + std::mutex& mutex() + { + return m_mtx; + } void put(T *ele) { @@ -112,19 +116,37 @@ public: return ele >= &m_base[0] && ele <= &m_base[m_base.size() -1]; } - /* Wait until cache is full.*/ - void wait() + + TPOOL_SUPPRESS_TSAN size_t size() + { + return m_cache.size(); + } + + /** Wait until cache is full + @param[in] lk - lock for the cache mutex + (which can be obtained with mutex()) */ + void wait(std::unique_lock<std::mutex> &lk) { - std::unique_lock<std::mutex> lk(m_mtx); m_waiters++; - while(!is_full()) + while (!is_full()) m_cv.wait(lk); m_waiters--; } + + /* Wait until cache is full.*/ + void wait() + { + std::unique_lock<std::mutex> lk(m_mtx); + wait(lk); + } - TPOOL_SUPPRESS_TSAN size_t size() + void resize(size_t count) { - return m_cache.size(); + assert(is_full()); + m_base.resize(count); + m_cache.resize(count); + for (size_t i = 0; i < count; i++) + m_cache[i] = &m_base[i]; } }; |