summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2020-03-14 20:52:17 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2020-03-14 22:48:10 +0100
commit39d0675652eff6affbe35520e7599842dbc53863 (patch)
treec5d7beb439bcedca027a8540ac5367abd1fbf54c
parent5754ea2eca0ffa191b4be46fdebf2d49c438f151 (diff)
downloadmariadb-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.result6
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_read_io_threads_basic.result14
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_write_io_threads_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_file_io_threads_basic.test7
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_read_io_threads_basic.test12
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_write_io_threads_basic.test8
-rw-r--r--storage/innobase/handler/ha_innodb.cc36
-rw-r--r--storage/innobase/os/os0file.cc82
-rw-r--r--tpool/tpool.h14
-rw-r--r--tpool/tpool_structs.h34
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];
}
};