mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 11:01:52 +01:00
Introduced a new timer based innodb thread concurrency. A new
parameter innodb_thread_concurrency_timer_based is used to get this new feature (it is set by default). The new feature is only available on platforms where atomic instructions are available.
This commit is contained in:
parent
aefc0acaf2
commit
5d615366ea
3 changed files with 130 additions and 10 deletions
|
@ -148,6 +148,9 @@ long innobase_max_merged_io = 64;
|
||||||
/* Number of background IO threads for read and write. */
|
/* Number of background IO threads for read and write. */
|
||||||
long innobase_read_io_threads, innobase_write_io_threads;
|
long innobase_read_io_threads, innobase_write_io_threads;
|
||||||
|
|
||||||
|
/* Use timer based InnoDB concurrency throttling flag */
|
||||||
|
static my_bool innobase_thread_concurrency_timer_based;
|
||||||
|
|
||||||
/* The following counter is used to convey information to InnoDB
|
/* The following counter is used to convey information to InnoDB
|
||||||
about server activity: in selects it is not sensible to call
|
about server activity: in selects it is not sensible to call
|
||||||
srv_active_wake_master_thread after each fetch or search, we only do
|
srv_active_wake_master_thread after each fetch or search, we only do
|
||||||
|
@ -1602,6 +1605,9 @@ innobase_init(
|
||||||
srv_n_log_files = (ulint) innobase_log_files_in_group;
|
srv_n_log_files = (ulint) innobase_log_files_in_group;
|
||||||
srv_log_file_size = (ulint) innobase_log_file_size;
|
srv_log_file_size = (ulint) innobase_log_file_size;
|
||||||
|
|
||||||
|
srv_thread_concurrency_timer_based =
|
||||||
|
(ibool) innobase_thread_concurrency_timer_based;
|
||||||
|
|
||||||
#ifdef UNIV_LOG_ARCHIVE
|
#ifdef UNIV_LOG_ARCHIVE
|
||||||
srv_log_archive_on = (ulint) innobase_log_archive;
|
srv_log_archive_on = (ulint) innobase_log_archive;
|
||||||
#endif /* UNIV_LOG_ARCHIVE */
|
#endif /* UNIV_LOG_ARCHIVE */
|
||||||
|
@ -8236,6 +8242,12 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
|
||||||
"Count of spin-loop rounds in InnoDB mutexes",
|
"Count of spin-loop rounds in InnoDB mutexes",
|
||||||
NULL, NULL, 20L, 0L, ~0L, 0);
|
NULL, NULL, 20L, 0L, ~0L, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_BOOL(thread_concurrency_timer_based,
|
||||||
|
innobase_thread_concurrency_timer_based,
|
||||||
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
|
"Use InnoDB timer based concurrency throttling. ",
|
||||||
|
NULL, NULL, TRUE);
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
|
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
|
||||||
PLUGIN_VAR_RQCMDARG,
|
PLUGIN_VAR_RQCMDARG,
|
||||||
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
|
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
|
||||||
|
@ -8278,6 +8290,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||||
MYSQL_SYSVAR(read_io_threads),
|
MYSQL_SYSVAR(read_io_threads),
|
||||||
MYSQL_SYSVAR(write_io_threads),
|
MYSQL_SYSVAR(write_io_threads),
|
||||||
MYSQL_SYSVAR(max_merged_io),
|
MYSQL_SYSVAR(max_merged_io),
|
||||||
|
MYSQL_SYSVAR(thread_concurrency_timer_based),
|
||||||
MYSQL_SYSVAR(file_per_table),
|
MYSQL_SYSVAR(file_per_table),
|
||||||
MYSQL_SYSVAR(flush_log_at_trx_commit),
|
MYSQL_SYSVAR(flush_log_at_trx_commit),
|
||||||
MYSQL_SYSVAR(flush_method),
|
MYSQL_SYSVAR(flush_method),
|
||||||
|
|
|
@ -89,6 +89,8 @@ extern ulint srv_awe_window_size;
|
||||||
extern ulint srv_mem_pool_size;
|
extern ulint srv_mem_pool_size;
|
||||||
extern ulint srv_lock_table_size;
|
extern ulint srv_lock_table_size;
|
||||||
|
|
||||||
|
extern ibool srv_thread_concurrency_timer_based;
|
||||||
|
|
||||||
extern ulint srv_n_file_io_threads;
|
extern ulint srv_n_file_io_threads;
|
||||||
/* Number of background IO threads for read and write. Replaces
|
/* Number of background IO threads for read and write. Replaces
|
||||||
* srv_n_file_io_threads. */
|
* srv_n_file_io_threads. */
|
||||||
|
|
|
@ -171,6 +171,7 @@ ulint srv_awe_window_size = 0; /* size in pages; MySQL inits
|
||||||
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
|
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
|
||||||
ulint srv_lock_table_size = ULINT_MAX;
|
ulint srv_lock_table_size = ULINT_MAX;
|
||||||
|
|
||||||
|
|
||||||
ulint srv_io_capacity = ULINT_MAX; /* Number of IO operations per
|
ulint srv_io_capacity = ULINT_MAX; /* Number of IO operations per
|
||||||
second the server can do */
|
second the server can do */
|
||||||
|
|
||||||
|
@ -288,19 +289,20 @@ Value 10 should be good if there are less than 4 processors + 4 disks in the
|
||||||
computer. Bigger computers need bigger values. Value 0 will disable the
|
computer. Bigger computers need bigger values. Value 0 will disable the
|
||||||
concurrency check. */
|
concurrency check. */
|
||||||
|
|
||||||
|
ibool srv_thread_concurrency_timer_based = TRUE;
|
||||||
ulong srv_thread_concurrency = 0;
|
ulong srv_thread_concurrency = 0;
|
||||||
ulong srv_commit_concurrency = 0;
|
ulong srv_commit_concurrency = 0;
|
||||||
|
|
||||||
os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data
|
os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data
|
||||||
structures */
|
structures */
|
||||||
lint srv_conc_n_threads = 0; /* number of OS threads currently
|
lint srv_conc_n_threads = 0; /* number of OS threads currently
|
||||||
inside InnoDB; it is not an error
|
inside InnoDB; it is not an error
|
||||||
if this drops temporarily below zero
|
if this drops temporarily below zero
|
||||||
because we do not demand that every
|
because we do not demand that every
|
||||||
thread increments this, but a thread
|
thread increments this, but a thread
|
||||||
waiting for a lock decrements this
|
waiting for a lock decrements this
|
||||||
temporarily */
|
temporarily */
|
||||||
ulint srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the
|
ulint srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the
|
||||||
FIFO for a permission to enter InnoDB
|
FIFO for a permission to enter InnoDB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1061,6 +1063,91 @@ ulong srv_max_purge_lag = 0;
|
||||||
Puts an OS thread to wait if there are too many concurrent threads
|
Puts an OS thread to wait if there are too many concurrent threads
|
||||||
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
|
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
inc_srv_conc_n_threads(lint *n_threads)
|
||||||
|
{
|
||||||
|
*n_threads = os_atomic_increment(&srv_conc_n_threads, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dec_srv_conc_n_threads()
|
||||||
|
{
|
||||||
|
os_atomic_increment(&srv_conc_n_threads, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_already_in_error(trx_t* trx)
|
||||||
|
{
|
||||||
|
ut_print_timestamp(stderr);
|
||||||
|
fputs(" InnoDB: Error: trying to declare trx"
|
||||||
|
" to enter InnoDB, but\n"
|
||||||
|
"InnoDB: it already is declared.\n", stderr);
|
||||||
|
trx_print(stderr, trx, 0);
|
||||||
|
putc('\n', stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enter_innodb_with_tickets(trx_t* trx)
|
||||||
|
{
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
srv_conc_enter_innodb_timer_based(trx_t* trx)
|
||||||
|
{
|
||||||
|
lint conc_n_threads;
|
||||||
|
ibool has_yielded = FALSE;
|
||||||
|
ulint has_slept = 0;
|
||||||
|
|
||||||
|
if (trx->declared_to_be_inside_innodb) {
|
||||||
|
print_already_in_error(trx);
|
||||||
|
}
|
||||||
|
retry:
|
||||||
|
if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
|
||||||
|
inc_srv_conc_n_threads(&conc_n_threads);
|
||||||
|
if (conc_n_threads <= srv_thread_concurrency) {
|
||||||
|
enter_innodb_with_tickets(trx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dec_srv_conc_n_threads(&conc_n_threads);
|
||||||
|
}
|
||||||
|
if (!has_yielded)
|
||||||
|
{
|
||||||
|
has_yielded = TRUE;
|
||||||
|
os_thread_yield();
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
if (trx->has_search_latch
|
||||||
|
|| NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
|
||||||
|
|
||||||
|
inc_srv_conc_n_threads(&conc_n_threads);
|
||||||
|
enter_innodb_with_tickets(trx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (has_slept < 2)
|
||||||
|
{
|
||||||
|
trx->op_info = "sleeping before entering InnoDB";
|
||||||
|
os_thread_sleep(10000);
|
||||||
|
trx->op_info = "";
|
||||||
|
has_slept++;
|
||||||
|
}
|
||||||
|
inc_srv_conc_n_threads(&conc_n_threads);
|
||||||
|
enter_innodb_with_tickets(trx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
srv_conc_exit_innodb_timer_based(trx_t* trx)
|
||||||
|
{
|
||||||
|
dec_srv_conc_n_threads();
|
||||||
|
trx->declared_to_be_inside_innodb = FALSE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
srv_conc_enter_innodb(
|
srv_conc_enter_innodb(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
|
@ -1091,15 +1178,17 @@ srv_conc_enter_innodb(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_ATOMIC
|
||||||
|
if (srv_thread_concurrency_timer_based) {
|
||||||
|
srv_conc_enter_innodb_timer_based(trx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
retry:
|
retry:
|
||||||
if (trx->declared_to_be_inside_innodb) {
|
if (trx->declared_to_be_inside_innodb) {
|
||||||
ut_print_timestamp(stderr);
|
print_already_in_error(trx);
|
||||||
fputs(" InnoDB: Error: trying to declare trx"
|
|
||||||
" to enter InnoDB, but\n"
|
|
||||||
"InnoDB: it already is declared.\n", stderr);
|
|
||||||
trx_print(stderr, trx, 0);
|
|
||||||
putc('\n', stderr);
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1226,17 +1315,25 @@ srv_conc_force_enter_innodb(
|
||||||
trx_t* trx) /* in: transaction object associated with the
|
trx_t* trx) /* in: transaction object associated with the
|
||||||
thread */
|
thread */
|
||||||
{
|
{
|
||||||
|
lint conc_n_threads;
|
||||||
|
|
||||||
if (UNIV_LIKELY(!srv_thread_concurrency)) {
|
if (UNIV_LIKELY(!srv_thread_concurrency)) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_ATOMIC
|
||||||
|
if (srv_thread_concurrency_timer_based) {
|
||||||
|
inc_srv_conc_n_threads(&conc_n_threads);
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
srv_conc_n_threads++;
|
srv_conc_n_threads++;
|
||||||
trx->declared_to_be_inside_innodb = TRUE;
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
trx->n_tickets_to_enter_innodb = 1;
|
trx->n_tickets_to_enter_innodb = 1;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,6 +1365,14 @@ srv_conc_force_exit_innodb(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_ATOMIC
|
||||||
|
if (srv_thread_concurrency_timer_based)
|
||||||
|
{
|
||||||
|
srv_conc_exit_innodb_timer_based(trx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
srv_conc_n_threads--;
|
srv_conc_n_threads--;
|
||||||
|
|
Loading…
Add table
Reference in a new issue