diff options
Diffstat (limited to 'storage/innobase/srv/srv0srv.c')
-rw-r--r-- | storage/innobase/srv/srv0srv.c | 408 |
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 |