summaryrefslogtreecommitdiff
path: root/storage/innobase/srv/srv0srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/srv/srv0srv.c')
-rw-r--r--storage/innobase/srv/srv0srv.c408
1 files changed, 245 insertions, 163 deletions
diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
index b2da43c188b..04503d25cd4 100644
--- a/storage/innobase/srv/srv0srv.c
+++ b/storage/innobase/srv/srv0srv.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -66,7 +66,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mem0mem.h"
#include "mem0pool.h"
#include "sync0sync.h"
-#include "thr0loc.h"
#include "que0que.h"
#include "log0recv.h"
#include "pars0pars.h"
@@ -87,10 +86,6 @@ Created 10/8/1995 Heikki Tuuri
#include "mysql/plugin.h"
#include "mysql/service_thd_wait.h"
-/* This is set to TRUE if the MySQL user has set it in MySQL; currently
-affects only FOREIGN KEY definition parsing */
-UNIV_INTERN ibool srv_lower_case_table_names = FALSE;
-
/* The following counter is incremented whenever there is some user activity
in the server */
UNIV_INTERN ulint srv_activity_count = 0;
@@ -267,12 +262,20 @@ UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
/* the number of purge threads to use from the worker pool (currently 0 or 1).*/
UNIV_INTERN ulong srv_n_purge_threads = 0;
-/* the number of records to purge in one batch */
+/* the number of pages to purge in one batch */
UNIV_INTERN ulong srv_purge_batch_size = 20;
+/* the number of rollback segments to use */
+UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS;
+
/* variable counts amount of data read in total (in bytes) */
UNIV_INTERN ulint srv_data_read = 0;
+/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
+NULL value when collecting statistics. By default, it is set to
+SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
+ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
+
/* here we count the amount of data written in total (in bytes) */
UNIV_INTERN ulint srv_data_written = 0;
@@ -424,6 +427,7 @@ UNIV_INTERN ulint srv_n_lock_wait_current_count = 0;
UNIV_INTERN ib_int64_t srv_n_lock_wait_time = 0;
UNIV_INTERN ulint srv_n_lock_max_wait_time = 0;
+UNIV_INTERN ulint srv_truncated_status_writes = 0;
/*
Set the following to 0 if you want InnoDB to write messages on
@@ -677,9 +681,7 @@ Unix.*/
/* Thread slot in the thread table */
struct srv_slot_struct{
- os_thread_id_t id; /*!< thread id */
- os_thread_t handle; /*!< thread handle */
- unsigned type:3; /*!< thread type: user, utility etc. */
+ unsigned type:1; /*!< thread type: user, utility etc. */
unsigned in_use:1; /*!< TRUE if this slot is in use */
unsigned suspended:1; /*!< TRUE if the thread is waiting
for the event of this slot */
@@ -694,6 +696,12 @@ struct srv_slot_struct{
/* Table for MySQL threads where they will be suspended to wait for locks */
UNIV_INTERN srv_slot_t* srv_mysql_table = NULL;
+UNIV_INTERN os_event_t srv_timeout_event;
+
+UNIV_INTERN os_event_t srv_monitor_event;
+
+UNIV_INTERN os_event_t srv_error_event;
+
UNIV_INTERN os_event_t srv_lock_timeout_thread_event;
UNIV_INTERN srv_sys_t* srv_sys = NULL;
@@ -780,6 +788,7 @@ srv_table_get_nth_slot(
/*===================*/
ulint index) /*!< in: index of the slot */
{
+ ut_ad(mutex_own(&kernel_mutex));
ut_a(index < OS_THREAD_MAX_N);
return(srv_sys->threads + index);
@@ -798,7 +807,7 @@ srv_get_n_threads(void)
mutex_enter(&kernel_mutex);
- for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
+ for (i = 0; i < SRV_MASTER + 1; i++) {
n_threads += srv_n_threads[i];
}
@@ -808,13 +817,46 @@ srv_get_n_threads(void)
return(n_threads);
}
+#ifdef UNIV_DEBUG
/*********************************************************************//**
-Reserves a slot in the thread table for the current thread. Also creates the
-thread local storage struct for the current thread. NOTE! The server mutex
-has to be reserved by the caller!
-@return reserved slot index */
+Validates the type of a thread table slot.
+@return TRUE if ok */
static
-ulint
+ibool
+srv_thread_type_validate(
+/*=====================*/
+ enum srv_thread_type type) /*!< in: thread type */
+{
+ switch (type) {
+ case SRV_WORKER:
+ case SRV_MASTER:
+ return(TRUE);
+ }
+ ut_error;
+ return(FALSE);
+}
+#endif /* UNIV_DEBUG */
+
+/*********************************************************************//**
+Gets the type of a thread table slot.
+@return thread type */
+static
+enum srv_thread_type
+srv_slot_get_type(
+/*==============*/
+ const srv_slot_t* slot) /*!< in: thread slot */
+{
+ enum srv_thread_type type = (enum srv_thread_type) slot->type;
+ ut_ad(srv_thread_type_validate(type));
+ return(type);
+}
+
+/*********************************************************************//**
+Reserves a slot in the thread table for the current thread.
+NOTE! The server mutex has to be reserved by the caller!
+@return reserved slot */
+static
+srv_slot_t*
srv_table_reserve_slot(
/*===================*/
enum srv_thread_type type) /*!< in: type of the thread */
@@ -822,8 +864,8 @@ srv_table_reserve_slot(
srv_slot_t* slot;
ulint i;
- ut_a(type > 0);
- ut_a(type <= SRV_MASTER);
+ ut_ad(srv_thread_type_validate(type));
+ ut_ad(mutex_own(&kernel_mutex));
i = 0;
slot = srv_table_get_nth_slot(i);
@@ -833,53 +875,37 @@ srv_table_reserve_slot(
slot = srv_table_get_nth_slot(i);
}
- ut_a(slot->in_use == FALSE);
-
slot->in_use = TRUE;
slot->suspended = FALSE;
slot->type = type;
- slot->id = os_thread_get_curr_id();
- slot->handle = os_thread_get_curr();
-
- thr_local_create();
+ ut_ad(srv_slot_get_type(slot) == type);
- thr_local_set_slot_no(os_thread_get_curr_id(), i);
-
- return(i);
+ return(slot);
}
/*********************************************************************//**
Suspends the calling thread to wait for the event in its thread slot.
-NOTE! The server mutex has to be reserved by the caller!
-@return event for the calling thread to wait */
+NOTE! The server mutex has to be reserved by the caller! */
static
-os_event_t
-srv_suspend_thread(void)
-/*====================*/
+void
+srv_suspend_thread(
+/*===============*/
+ srv_slot_t* slot) /*!< in/out: thread slot */
{
- srv_slot_t* slot;
- os_event_t event;
- ulint slot_no;
enum srv_thread_type type;
ut_ad(mutex_own(&kernel_mutex));
-
- slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
+ ut_ad(slot->in_use);
+ ut_ad(!slot->suspended);
if (srv_print_thread_releases) {
fprintf(stderr,
"Suspending thread %lu to slot %lu\n",
- (ulong) os_thread_get_curr_id(), (ulong) slot_no);
+ (ulong) os_thread_get_curr_id(),
+ (ulong) (slot - srv_sys->threads));
}
- slot = srv_table_get_nth_slot(slot_no);
-
- type = slot->type;
-
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
-
- event = slot->event;
+ type = srv_slot_get_type(slot);
slot->suspended = TRUE;
@@ -887,9 +913,7 @@ srv_suspend_thread(void)
srv_n_threads_active[type]--;
- os_event_reset(event);
-
- return(event);
+ os_event_reset(slot->event);
}
/*********************************************************************//**
@@ -908,8 +932,7 @@ srv_release_threads(
ulint i;
ulint count = 0;
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
+ ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
ut_ad(mutex_own(&kernel_mutex));
@@ -917,7 +940,8 @@ srv_release_threads(
slot = srv_table_get_nth_slot(i);
- if (slot->in_use && slot->type == type && slot->suspended) {
+ if (slot->in_use && slot->suspended
+ && srv_slot_get_type(slot) == type) {
slot->suspended = FALSE;
@@ -927,10 +951,9 @@ srv_release_threads(
if (srv_print_thread_releases) {
fprintf(stderr,
- "Releasing thread %lu type %lu"
+ "Releasing thread type %lu"
" from slot %lu\n",
- (ulong) slot->id, (ulong) type,
- (ulong) i);
+ (ulong) type, (ulong) i);
}
count++;
@@ -945,31 +968,35 @@ srv_release_threads(
}
/*********************************************************************//**
-Returns the calling thread type.
-@return SRV_COM, ... */
+Check whether thread type has reserved a slot. Return the first slot that
+is found. This works because we currently have only 1 thread of each type.
+@return slot number or ULINT_UNDEFINED if not found*/
UNIV_INTERN
-enum srv_thread_type
-srv_get_thread_type(void)
-/*=====================*/
+ulint
+srv_thread_has_reserved_slot(
+/*=========================*/
+ enum srv_thread_type type) /*!< in: thread type to check */
{
- ulint slot_no;
- srv_slot_t* slot;
- enum srv_thread_type type;
+ ulint i;
+ ulint slot_no = ULINT_UNDEFINED;
+ ut_ad(srv_thread_type_validate(type));
mutex_enter(&kernel_mutex);
- slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
-
- slot = srv_table_get_nth_slot(slot_no);
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ srv_slot_t* slot;
- type = slot->type;
+ slot = srv_table_get_nth_slot(i);
- ut_ad(type >= SRV_WORKER);
- ut_ad(type <= SRV_MASTER);
+ if (slot->in_use && slot->type == type) {
+ slot_no = i;
+ break;
+ }
+ }
mutex_exit(&kernel_mutex);
- return(type);
+ return(slot_no);
}
/*********************************************************************//**
@@ -991,26 +1018,28 @@ srv_init(void)
mutex_create(srv_innodb_monitor_mutex_key,
&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
- srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
+ srv_sys->threads = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
- slot = srv_table_get_nth_slot(i);
- slot->in_use = FALSE;
- slot->type=0; /* Avoid purify errors */
+ slot = srv_sys->threads + i;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
- srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
+ srv_mysql_table = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
slot = srv_mysql_table + i;
- slot->in_use = FALSE;
- slot->type = 0;
slot->event = os_event_create(NULL);
ut_a(slot->event);
}
+ srv_error_event = os_event_create(NULL);
+
+ srv_timeout_event = os_event_create(NULL);
+
+ srv_monitor_event = os_event_create(NULL);
+
srv_lock_timeout_thread_event = os_event_create(NULL);
for (i = 0; i < SRV_MASTER + 1; i++) {
@@ -1087,7 +1116,6 @@ srv_general_init(void)
os_sync_init();
sync_init();
mem_init(srv_mem_pool_size);
- thr_local_init();
}
/*======================= InnoDB Server FIFO queue =======================*/
@@ -1109,6 +1137,10 @@ srv_conc_enter_innodb(
srv_conc_slot_t* slot = NULL;
ulint i;
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (trx->mysql_thd != NULL
&& thd_is_replication_slave_thread(trx->mysql_thd)) {
@@ -1232,9 +1264,13 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
+ ut_ad(!trx->has_search_latch);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
trx->op_info = "waiting in InnoDB queue";
- thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
+ thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
os_event_wait(slot->event);
thd_wait_end(trx->mysql_thd);
@@ -1267,6 +1303,10 @@ srv_conc_force_enter_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (UNIV_LIKELY(!srv_thread_concurrency)) {
return;
@@ -1338,6 +1378,10 @@ srv_conc_force_exit_innodb(
if (slot != NULL) {
os_event_set(slot->event);
}
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
}
/*********************************************************************//**
@@ -1349,6 +1393,10 @@ srv_conc_exit_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
if (trx->n_tickets_to_enter_innodb > 0) {
/* We will pretend the thread is still inside InnoDB though it
now leaves the InnoDB engine. In this way we save
@@ -1446,7 +1494,7 @@ srv_table_reserve_slot_for_mysql(void)
while (slot->in_use) {
i++;
- if (i >= OS_THREAD_MAX_N) {
+ if (UNIV_UNLIKELY(i >= OS_THREAD_MAX_N)) {
ut_print_timestamp(stderr);
@@ -1465,10 +1513,9 @@ srv_table_reserve_slot_for_mysql(void)
slot = srv_mysql_table + i;
fprintf(stderr,
- "Slot %lu: thread id %lu, type %lu,"
+ "Slot %lu: thread type %lu,"
" in use %lu, susp %lu, time %lu\n",
(ulong) i,
- (ulong) os_thread_pf(slot->id),
(ulong) slot->type,
(ulong) slot->in_use,
(ulong) slot->suspended,
@@ -1485,8 +1532,6 @@ srv_table_reserve_slot_for_mysql(void)
ut_a(slot->in_use == FALSE);
slot->in_use = TRUE;
- slot->id = os_thread_get_curr_id();
- slot->handle = os_thread_get_curr();
return(slot);
}
@@ -1573,17 +1618,6 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex);
- if (trx->declared_to_be_inside_innodb) {
-
- was_declared_inside_innodb = TRUE;
-
- /* We must declare this OS thread to exit InnoDB, since a
- possible other thread holding a lock which this thread waits
- for must be allowed to enter, sooner or later */
-
- srv_conc_force_exit_innodb(trx);
- }
-
had_dict_lock = trx->dict_operation_lock_mode;
switch (had_dict_lock) {
@@ -1592,6 +1626,18 @@ srv_suspend_mysql_thread(
row_mysql_unfreeze_data_dictionary(trx);
break;
case RW_X_LATCH:
+ /* There should never be a lock wait when the
+ dictionary latch is reserved in X mode. Dictionary
+ transactions should only acquire locks on dictionary
+ tables, not other tables. All access to dictionary
+ tables should be covered by dictionary
+ transactions. */
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: dict X latch held in "
+ "srv_suspend_mysql_thread\n", stderr);
+ /* This should never occur. This incorrect handling
+ was added in the early development of
+ ha_innobase::add_index() in InnoDB Plugin 1.0. */
/* Release fast index creation latch */
row_mysql_unlock_data_dictionary(trx);
break;
@@ -1599,12 +1645,34 @@ srv_suspend_mysql_thread(
ut_a(trx->dict_operation_lock_mode == 0);
+ if (trx->declared_to_be_inside_innodb) {
+
+ was_declared_inside_innodb = TRUE;
+
+ /* We must declare this OS thread to exit InnoDB, since a
+ possible other thread holding a lock which this thread waits
+ for must be allowed to enter, sooner or later */
+
+ srv_conc_force_exit_innodb(trx);
+ }
+
/* Suspend this thread and wait for the event. */
- thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
+ thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_LOCK);
os_event_wait(event);
thd_wait_end(trx->mysql_thd);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (was_declared_inside_innodb) {
+
+ /* Return back inside InnoDB */
+
+ srv_conc_force_enter_innodb(trx);
+ }
+
/* After resuming, reacquire the data dictionary latch if
necessary. */
@@ -1613,17 +1681,13 @@ srv_suspend_mysql_thread(
row_mysql_freeze_data_dictionary(trx);
break;
case RW_X_LATCH:
+ /* This should never occur. This incorrect handling
+ was added in the early development of
+ ha_innobase::add_index() in InnoDB Plugin 1.0. */
row_mysql_lock_data_dictionary(trx);
break;
}
- if (was_declared_inside_innodb) {
-
- /* Return back inside InnoDB */
-
- srv_conc_force_enter_innodb(trx);
- }
-
mutex_enter(&kernel_mutex);
/* Release the slot for others to use */
@@ -2017,6 +2081,7 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_inserted = srv_n_rows_inserted;
export_vars.innodb_rows_updated = srv_n_rows_updated;
export_vars.innodb_rows_deleted = srv_n_rows_deleted;
+ export_vars.innodb_truncated_status_writes = srv_truncated_status_writes;
mutex_exit(&srv_innodb_monitor_mutex);
}
@@ -2032,6 +2097,7 @@ srv_monitor_thread(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ ib_int64_t sig_count;
double time_elapsed;
time_t current_time;
time_t last_table_monitor_time;
@@ -2050,26 +2116,28 @@ srv_monitor_thread(
#endif
UT_NOT_USED(arg);
- srv_last_monitor_time = time(NULL);
- last_table_monitor_time = time(NULL);
- last_tablespace_monitor_time = time(NULL);
- last_monitor_time = time(NULL);
+ srv_last_monitor_time = ut_time();
+ last_table_monitor_time = ut_time();
+ last_tablespace_monitor_time = ut_time();
+ last_monitor_time = ut_time();
mutex_skipped = 0;
last_srv_print_monitor = srv_print_innodb_monitor;
loop:
srv_monitor_active = TRUE;
/* Wake up every 5 seconds to see if we need to print
- monitor information. */
+ monitor information or if signalled at shutdown. */
- os_thread_sleep(5000000);
+ sig_count = os_event_reset(srv_monitor_event);
- current_time = time(NULL);
+ os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
+
+ current_time = ut_time();
time_elapsed = difftime(current_time, last_monitor_time);
if (time_elapsed > 15) {
- last_monitor_time = time(NULL);
+ last_monitor_time = ut_time();
if (srv_print_innodb_monitor) {
/* Reset mutex_skipped counter everytime
@@ -2113,7 +2181,7 @@ loop:
if (srv_print_innodb_tablespace_monitor
&& difftime(current_time,
last_tablespace_monitor_time) > 60) {
- last_tablespace_monitor_time = time(NULL);
+ last_tablespace_monitor_time = ut_time();
fputs("========================"
"========================\n",
@@ -2139,7 +2207,7 @@ loop:
if (srv_print_innodb_table_monitor
&& difftime(current_time, last_table_monitor_time) > 60) {
- last_table_monitor_time = time(NULL);
+ last_table_monitor_time = ut_time();
fputs("===========================================\n",
stderr);
@@ -2199,16 +2267,20 @@ srv_lock_timeout_thread(
ibool some_waits;
double wait_time;
ulint i;
+ ib_int64_t sig_count;
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_lock_timeout_thread_key);
#endif
loop:
+
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
- os_thread_sleep(1000000);
+ sig_count = os_event_reset(srv_timeout_event);
+
+ os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
srv_lock_timeout_active = TRUE;
@@ -2303,6 +2375,13 @@ srv_error_monitor_thread(
ulint fatal_cnt = 0;
ib_uint64_t old_lsn;
ib_uint64_t new_lsn;
+ ib_int64_t sig_count;
+ /* longest waiting thread for a semaphore */
+ os_thread_id_t waiter = os_thread_get_curr_id();
+ os_thread_id_t old_waiter = waiter;
+ /* the semaphore that is being waited for */
+ const void* sema = NULL;
+ const void* old_sema = NULL;
old_lsn = srv_start_lsn;
@@ -2356,7 +2435,8 @@ loop:
sync_arr_wake_threads_if_sema_free();
- if (sync_array_print_long_waits()) {
+ if (sync_array_print_long_waits(&waiter, &sema)
+ && sema == old_sema && os_thread_eq(waiter, old_waiter)) {
fatal_cnt++;
if (fatal_cnt > 10) {
@@ -2371,6 +2451,8 @@ loop:
}
} else {
fatal_cnt = 0;
+ old_waiter = waiter;
+ old_sema = sema;
}
/* Flush stderr so that a database user gets the output
@@ -2378,7 +2460,9 @@ loop:
fflush(stderr);
- os_thread_sleep(1000000);
+ sig_count = os_event_reset(srv_error_event);
+
+ os_event_wait_time_low(srv_error_event, 1000000, sig_count);
if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
@@ -2408,7 +2492,7 @@ srv_is_any_background_thread_active(void)
mutex_enter(&kernel_mutex);
- for (i = SRV_COM; i <= SRV_MASTER; ++i) {
+ for (i = 0; i <= SRV_MASTER; ++i) {
if (srv_n_threads_active[i] != 0) {
ret = TRUE;
break;
@@ -2562,7 +2646,7 @@ srv_master_thread(
os_thread_create */
{
buf_pool_stat_t buf_stat;
- os_event_t event;
+ srv_slot_t* slot;
ulint old_activity_count;
ulint n_pages_purged = 0;
ulint n_bytes_merged;
@@ -2588,10 +2672,10 @@ srv_master_thread(
srv_main_thread_process_no = os_proc_get_number();
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
- srv_table_reserve_slot(SRV_MASTER);
-
mutex_enter(&kernel_mutex);
+ slot = srv_table_reserve_slot(SRV_MASTER);
+
srv_n_threads_active[SRV_MASTER]++;
mutex_exit(&kernel_mutex);
@@ -2622,11 +2706,28 @@ loop:
when there is database activity */
srv_last_log_flush_time = time(NULL);
- next_itr_time = ut_time_ms();
+
+ /* Sleep for 1 second on entrying the for loop below the first time. */
+ next_itr_time = ut_time_ms() + 1000;
for (i = 0; i < 10; i++) {
ulint cur_time = ut_time_ms();
+ /* ALTER TABLE in MySQL requires on Unix that the table handler
+ can drop tables lazily after there no longer are SELECT
+ queries to them. */
+
+ srv_main_thread_op_info = "doing background drop tables";
+
+ row_drop_tables_for_mysql_in_background();
+
+ srv_main_thread_op_info = "";
+
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
+
+ goto background_loop;
+ }
+
buf_get_total_stat(&buf_stat);
n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
@@ -2635,7 +2736,8 @@ loop:
srv_main_thread_op_info = "sleeping";
srv_main_1_second_loops++;
- if (next_itr_time > cur_time) {
+ if (next_itr_time > cur_time
+ && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
/* Get sleep interval in micro seconds. We use
ut_min() to avoid long sleep in case of
@@ -2649,21 +2751,6 @@ loop:
/* Each iteration should happen at 1 second interval. */
next_itr_time = ut_time_ms() + 1000;
- /* ALTER TABLE in MySQL requires on Unix that the table handler
- can drop tables lazily after there no longer are SELECT
- queries to them. */
-
- srv_main_thread_op_info = "doing background drop tables";
-
- row_drop_tables_for_mysql_in_background();
-
- srv_main_thread_op_info = "";
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
- goto background_loop;
- }
-
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
@@ -2841,7 +2928,9 @@ background_loop:
MySQL tries to drop a table while there are still open handles
to it and we had to put it to the background drop queue.) */
- os_thread_sleep(100000);
+ if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+ os_thread_sleep(100000);
+ }
}
if (srv_n_purge_threads == 0) {
@@ -2974,7 +3063,7 @@ suspend_thread:
goto loop;
}
- event = srv_suspend_thread();
+ srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
@@ -2984,22 +3073,16 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
- os_event_wait(event);
+ os_event_wait(slot->event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- /* This is only extra safety, the thread should exit
- already when the event wait ends */
-
os_thread_exit(NULL);
-
}
/* When there is user activity, InnoDB will set the event and the
main thread goes back to loop. */
goto loop;
-
- OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
}
/*********************************************************************//**
@@ -3013,7 +3096,7 @@ srv_purge_thread(
required by os_thread_create */
{
srv_slot_t* slot;
- ulint slot_no = ULINT_UNDEFINED;
+ ulint retries = 0;
ulint n_total_purged = ULINT_UNDEFINED;
ut_a(srv_n_purge_threads == 1);
@@ -3029,9 +3112,7 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
- slot_no = srv_table_reserve_slot(SRV_WORKER);
-
- slot = srv_table_get_nth_slot(slot_no);
+ slot = srv_table_reserve_slot(SRV_WORKER);
++srv_n_threads_active[SRV_WORKER];
@@ -3039,7 +3120,7 @@ srv_purge_thread(
while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
- ulint n_pages_purged;
+ ulint n_pages_purged = 0;
/* If there are very few records to purge or the last
purge didn't purge any records then wait for activity.
@@ -3047,17 +3128,18 @@ srv_purge_thread(
because in the worst case we will end up waiting for
the next purge event. */
if (trx_sys->rseg_history_len < srv_purge_batch_size
- || n_total_purged == 0) {
-
- os_event_t event;
+ || (n_total_purged == 0
+ && retries >= TRX_SYS_N_RSEGS)) {
mutex_enter(&kernel_mutex);
- event = srv_suspend_thread();
+ srv_suspend_thread(slot);
mutex_exit(&kernel_mutex);
- os_event_wait(event);
+ os_event_wait(slot->event);
+
+ retries = 0;
}
/* Check for shutdown and whether we should do purge at all. */
@@ -3068,7 +3150,12 @@ srv_purge_thread(
break;
}
- n_total_purged = 0;
+ if (n_total_purged == 0 && retries <= TRX_SYS_N_RSEGS) {
+ ++retries;
+ } else if (n_total_purged > 0) {
+ retries = 0;
+ n_total_purged = 0;
+ }
/* Purge until there are no more records to purge and there is
no change in configuration or server state. */
@@ -3084,16 +3171,11 @@ srv_purge_thread(
mutex_enter(&kernel_mutex);
- ut_ad(srv_table_get_nth_slot(slot_no) == slot);
-
/* Decrement the active count. */
- srv_suspend_thread();
+ srv_suspend_thread(slot);
slot->in_use = FALSE;
- /* Free the thread local memory. */
- thr_local_free(os_thread_get_curr_id());
-
mutex_exit(&kernel_mutex);
#ifdef UNIV_DEBUG_THREAD_CREATION