Commit 6870f17b authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

Merge remote-tracking branch 'origin/bb-10.10-MDEV-11026' into 10.11

parents 7253cdf8 c8e3bcf7
......@@ -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
......
......@@ -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;
......@@ -15,7 +15,13 @@ 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
select @@innodb_write_io_threads;
@@innodb_write_io_threads
2
set global innodb_write_io_threads=64;
select @@innodb_write_io_threads;
@@innodb_write_io_threads
64
set global innodb_write_io_threads=@n;
......@@ -1349,7 +1349,7 @@ NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 64
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY YES
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_READ_ONLY
SESSION_VALUE NULL
......@@ -1697,5 +1697,5 @@ NUMERIC_MIN_VALUE 2
NUMERIC_MAX_VALUE 64
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY YES
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
......@@ -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
......
......@@ -19,10 +19,18 @@ 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;
--disable_warnings
set global innodb_read_io_threads = 1;
--enable_warnings
select @@innodb_read_io_threads;
--disable_warnings
set global innodb_read_io_threads=64;
--enable_warnings
select @@innodb_read_io_threads;
--error ER_GLOBAL_VARIABLE
set session innodb_read_io_threads=1;
set global innodb_read_io_threads=@n;
......@@ -19,10 +19,18 @@ 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;
--disable_warnings
set global innodb_write_io_threads=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set session innodb_write_io_threads=1;
--enable_warnings
select @@innodb_write_io_threads;
--disable_warnings
set global innodb_write_io_threads=64;
--enable_warnings
select @@innodb_write_io_threads;
--disable_warnings
set global innodb_write_io_threads=@n;
--enable_warnings
......@@ -19271,15 +19271,44 @@ 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 not 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)
{
srv_n_read_io_threads = *static_cast<const uint*>(save);
innodb_update_io_thread_count(thd, srv_n_read_io_threads, srv_n_write_io_threads);
}
static void innodb_write_io_threads_update(THD* thd, struct st_mysql_sys_var*, void*, const void* save)
{
srv_n_write_io_threads = *static_cast<const uint*>(save);
innodb_update_io_thread_count(thd, srv_n_read_io_threads, srv_n_write_io_threads);
}
static MYSQL_SYSVAR_UINT(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_UINT(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, 2, 64, 0);
NULL, innodb_write_io_threads_update, 4, 2, 64, 0);
static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
......
......@@ -83,8 +83,7 @@ class io_slots
int m_max_aio;
public:
io_slots(int max_submitted_io, int max_callback_concurrency) :
m_cache(max_submitted_io),
m_group(max_callback_concurrency),
m_cache(max_submitted_io), m_group(max_callback_concurrency, false),
m_max_aio(max_submitted_io)
{
}
......@@ -105,6 +104,11 @@ class io_slots
}
/* Wait for completions of all AIO operations */
void wait(std::unique_lock<std::mutex> &lk)
{
m_cache.wait(lk);
}
void wait()
{
m_cache.wait();
......@@ -124,6 +128,24 @@ class io_slots
{
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;
......@@ -3691,6 +3713,58 @@ int os_aio_init()
}
/**
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());
read_slots->wait(lk_read);
write_slots->wait(lk_write);
/* 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 events= max_read_events + max_write_events;
/** Do the Linux AIO dance (this will try to create a new
io context with changed max_events ,etc*/
if (int ret= srv_thread_pool->reconfigure_aio(srv_use_native_aio, events))
{
/** 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(static_cast<int>(n_reader_threads));
write_slots->task_group().set_max_tasks(static_cast<int>(n_writer_threads));
return ret;
}
/* Allocation succeeded, resize the slots*/
read_slots->resize(max_read_events, static_cast<int>(n_reader_threads), lk_read);
write_slots->resize(max_write_events, static_cast<int>(n_writer_threads), lk_write);
return 0;
}
void os_aio_free()
{
srv_thread_pool->disable_aio();
......
......@@ -25,11 +25,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
#endif
namespace tpool
{
task_group::task_group(unsigned int max_concurrency) :
/**
Task_group constructor
@param max_threads - maximum number of threads allowed to execute
tasks from the group at the same time.
@param enable_task_release - if true (default), task::release() will be
called after task execution.'false' should only be used in rare cases
when accessing memory, pointed by task structures, would be unsafe after.
the callback. Also 'false' is only possible ,if task::release() is a trivial function
*/
task_group::task_group(unsigned int max_concurrency,
bool enable_task_release)
:
m_queue(8),
m_mtx(),
m_tasks_running(),
m_max_concurrent_tasks(max_concurrency)
m_max_concurrent_tasks(max_concurrency),
m_enable_task_release(enable_task_release)
{};
void task_group::set_max_tasks(unsigned int max_concurrency)
......@@ -53,7 +68,8 @@ namespace tpool
if (t)
{
t->m_func(t->m_arg);
t->release();
if (m_enable_task_release)
t->release();
}
lk.lock();
......
......@@ -68,8 +68,10 @@ class task_group
std::condition_variable m_cv;
unsigned int m_tasks_running;
unsigned int m_max_concurrent_tasks;
const bool m_enable_task_release;
public:
task_group(unsigned int max_concurrency= 100000);
task_group(unsigned int max_concurrency= 100000, bool m_enable_task_release= true);
void set_max_tasks(unsigned int max_concurrent_tasks);
void execute(task* t);
void cancel_pending(task *t);
......@@ -231,6 +233,20 @@ class thread_pool
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();
......
......@@ -94,6 +94,10 @@ template<typename T> class cache
return ret;
}
std::mutex& mutex()
{
return m_mtx;
}
void put(T *ele)
{
......@@ -112,19 +116,37 @@ template<typename T> class cache
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--;
}
TPOOL_SUPPRESS_TSAN size_t size()
/* Wait until cache is full.*/
void wait()
{
return m_cache.size();
std::unique_lock<std::mutex> lk(m_mtx);
wait(lk);
}
void resize(size_t count)
{
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];
}
};
......
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