diff options
Diffstat (limited to 'sql/mysqld.cc')
-rw-r--r-- | sql/mysqld.cc | 926 |
1 files changed, 615 insertions, 311 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dcc9aec97a6..7066eba00ac 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -52,6 +52,7 @@ #include "des_key_file.h" // load_des_key_file #include "sql_manager.h" // stop_handle_manager, start_handle_manager #include "sql_expression_cache.h" // subquery_cache_miss, subquery_cache_hit +#include "sys_vars_shared.h" #include <m_ctype.h> #include <my_dir.h> @@ -464,14 +465,15 @@ ulong delay_key_write_options; uint protocol_version; uint lower_case_table_names; ulong tc_heuristic_recover= 0; -uint volatile thread_count; +int32 thread_count; int32 thread_running; +int32 slave_open_temp_tables; ulong thread_created; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; ulong what_to_log; -ulong slow_launch_time, slave_open_temp_tables; -ulong open_files_limit, max_binlog_size, max_relay_log_size; +ulong slow_launch_time; +ulong open_files_limit, max_binlog_size; ulong slave_trans_retries; uint slave_net_timeout; ulong slave_exec_mode_options; @@ -488,6 +490,9 @@ ulong executed_events=0; query_id_t global_query_id; my_atomic_rwlock_t global_query_id_lock; my_atomic_rwlock_t thread_running_lock; +my_atomic_rwlock_t thread_count_lock; +my_atomic_rwlock_t statistics_lock; +my_atomic_rwlock_t slave_executed_entries_lock; ulong aborted_threads, aborted_connects; ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; @@ -497,6 +502,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong max_connections, max_connect_errors; ulong extra_max_connections; +ulong slave_retried_transactions; ulonglong denied_connections; my_decimal decimal_zero; @@ -539,6 +545,11 @@ ulong rpl_recovery_rank=0; */ ulong stored_program_cache_size= 0; +ulong opt_slave_parallel_threads= 0; +ulong opt_binlog_commit_wait_count= 0; +ulong opt_binlog_commit_wait_usec= 0; +ulong opt_slave_parallel_max_queued= 131072; + const double log_10[] = { 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, @@ -616,7 +627,8 @@ MYSQL_FILE *bootstrap_file; int bootstrap_error; I_List<THD> threads; -Rpl_filter* rpl_filter; +Rpl_filter* cur_rpl_filter; +Rpl_filter* global_rpl_filter; Rpl_filter* binlog_filter; THD *first_global_thread() @@ -653,12 +665,13 @@ SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache; SHOW_COMP_OPTION have_geometry, have_rtree_keys; SHOW_COMP_OPTION have_crypt, have_compress; SHOW_COMP_OPTION have_profiling; +SHOW_COMP_OPTION have_openssl; /* Thread specific variables */ pthread_key(MEM_ROOT**,THR_MALLOC); pthread_key(THD*, THR_THD); -mysql_mutex_t LOCK_thread_count; +mysql_mutex_t LOCK_thread_count, LOCK_thread_cache; mysql_mutex_t LOCK_status, LOCK_error_log, LOCK_short_uuid_generator, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, @@ -689,8 +702,7 @@ pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; -int mysqld_server_started= 0; - +int mysqld_server_started=0, mysqld_server_initialized= 0; File_parser_dummy_hook file_parser_dummy_hook; /* replication parameters, if master_host is not NULL, we are a slave */ @@ -732,14 +744,16 @@ char **orig_argv; #ifdef HAVE_PSI_INTERFACE #ifdef HAVE_MMAP -PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool; +PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool, + key_LOCK_pending_checkpoint; #endif /* HAVE_MMAP */ #ifdef HAVE_OPENSSL PSI_mutex_key key_LOCK_des_key_file; #endif /* HAVE_OPENSSL */ -PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, +PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, + key_BINLOG_LOCK_binlog_background_thread, key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi, key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create, key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log, @@ -753,16 +767,20 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, key_master_info_sleep_lock, key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, - key_relay_log_info_sleep_lock, + key_rpl_group_info_sleep_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, - key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count, + key_LOCK_error_messages, key_LOG_INFO_lock, + key_LOCK_thread_count, key_LOCK_thread_cache, key_PARTITION_LOCK_auto_inc; PSI_mutex_key key_RELAYLOG_LOCK_index; +PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, + key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry; PSI_mutex_key key_LOCK_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, key_LOCK_global_index_stats, - key_LOCK_wakeup_ready; + key_LOCK_wakeup_ready, key_LOCK_wait_commit; +PSI_mutex_key key_LOCK_gtid_waiting; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; @@ -773,6 +791,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_sync, "TC_LOG_MMAP::LOCK_sync", 0}, { &key_LOCK_active, "TC_LOG_MMAP::LOCK_active", 0}, { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pool", 0}, + { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pending_checkpoint", 0}, #endif /* HAVE_MMAP */ #ifdef HAVE_OPENSSL @@ -780,7 +799,8 @@ static PSI_mutex_info all_server_mutexes[]= #endif /* HAVE_OPENSSL */ { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0}, - { &key_BINLOG_LOCK_prep_xids, "MYSQL_BIN_LOG::LOCK_prep_xids", 0}, + { &key_BINLOG_LOCK_xid_list, "MYSQL_BIN_LOG::LOCK_xid_list", 0}, + { &key_BINLOG_LOCK_binlog_background_thread, "MYSQL_BIN_LOG::LOCK_binlog_background_thread", 0}, { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0}, { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0}, { &key_hash_filo_lock, "hash_filo::lock", 0}, @@ -805,6 +825,8 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_global_table_stats, "LOCK_global_table_stats", PSI_FLAG_GLOBAL}, { &key_LOCK_global_index_stats, "LOCK_global_index_stats", PSI_FLAG_GLOBAL}, { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0}, + { &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0}, + { &key_LOCK_gtid_waiting, "gtid_waiting::LOCK_gtid_waiting", 0}, { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0}, { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL}, { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL}, @@ -816,7 +838,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0}, { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0}, { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0}, - { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0}, + { &key_rpl_group_info_sleep_lock, "Rpl_group_info::sleep_lock", 0}, { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0}, { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0}, { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL}, @@ -824,7 +846,13 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, - { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} + { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL}, + { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}, + { &key_LOCK_slave_state, "LOCK_slave_state", 0}, + { &key_LOCK_binlog_state, "LOCK_binlog_state", 0}, + { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0}, + { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0}, + { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0} }; PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, @@ -848,7 +876,9 @@ static PSI_rwlock_info all_server_rwlocks[]= PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool; #endif /* HAVE_MMAP */ -PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, +PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, + key_BINLOG_COND_binlog_background_thread, + key_BINLOG_COND_binlog_background_thread_end, key_COND_cache_status_changed, key_COND_manager, key_COND_rpl_status, key_COND_server_started, key_delayed_insert_cond, key_delayed_insert_cond_client, @@ -857,13 +887,17 @@ PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, key_master_info_sleep_cond, key_relay_log_info_data_cond, key_relay_log_info_log_space_cond, key_relay_log_info_start_cond, key_relay_log_info_stop_cond, - key_relay_log_info_sleep_cond, + key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, key_BINLOG_COND_queue_busy; -PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready; +PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, + key_COND_wait_commit; PSI_cond_key key_RELAYLOG_COND_queue_busy; PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy; +PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool, + key_COND_parallel_entry, key_COND_prepare_ordered; +PSI_cond_key key_COND_wait_gtid; static PSI_cond_info all_server_conds[]= { @@ -876,12 +910,15 @@ static PSI_cond_info all_server_conds[]= { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0}, { &key_TC_LOG_MMAP_COND_queue_busy, "TC_LOG_MMAP::COND_queue_busy", 0}, #endif /* HAVE_MMAP */ - { &key_BINLOG_COND_prep_xids, "MYSQL_BIN_LOG::COND_prep_xids", 0}, + { &key_BINLOG_COND_xid_list, "MYSQL_BIN_LOG::COND_xid_list", 0}, { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0}, + { &key_BINLOG_COND_binlog_background_thread, "MYSQL_BIN_LOG::COND_binlog_background_thread", 0}, + { &key_BINLOG_COND_binlog_background_thread_end, "MYSQL_BIN_LOG::COND_binlog_background_thread_end", 0}, { &key_BINLOG_COND_queue_busy, "MYSQL_BIN_LOG::COND_queue_busy", 0}, { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0}, { &key_RELAYLOG_COND_queue_busy, "MYSQL_RELAY_LOG::COND_queue_busy", 0}, { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 0}, + { &key_COND_wait_commit, "wait_for_commit::COND_wait_commit", 0}, { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0}, { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL}, { &key_COND_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL}, @@ -897,17 +934,23 @@ static PSI_cond_info all_server_conds[]= { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0}, { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0}, { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0}, - { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0}, + { &key_rpl_group_info_sleep_cond, "Rpl_group_info::sleep_cond", 0}, { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0}, { &key_user_level_lock_cond, "User_level_lock::cond", 0}, { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL}, { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL}, - { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL} + { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL}, + { &key_COND_rpl_thread, "COND_rpl_thread", 0}, + { &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0}, + { &key_COND_parallel_entry, "COND_parallel_entry", 0}, + { &key_COND_prepare_ordered, "COND_prepare_ordered", 0}, + { &key_COND_wait_gtid, "COND_wait_gtid", 0} }; PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_main, - key_thread_one_connection, key_thread_signal_hand; + key_thread_one_connection, key_thread_signal_hand, + key_thread_slave_init, key_rpl_parallel_thread; static PSI_thread_info all_server_threads[]= { @@ -932,7 +975,9 @@ static PSI_thread_info all_server_threads[]= { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL}, { &key_thread_main, "main", PSI_FLAG_GLOBAL}, { &key_thread_one_connection, "one_connection", 0}, - { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL} + { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL}, + { &key_thread_slave_init, "slave_init", PSI_FLAG_GLOBAL}, + { &key_rpl_parallel_thread, "rpl_parallel_thread", 0} }; PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest, @@ -944,6 +989,7 @@ PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest, key_file_trg, key_file_trn, key_file_init; PSI_file_key key_file_query_log, key_file_slow_log; PSI_file_key key_file_relaylog, key_file_relaylog_index; +PSI_file_key key_file_binlog_state; static PSI_file_info all_server_files[]= { @@ -974,7 +1020,8 @@ static PSI_file_info all_server_files[]= { &key_file_tclog, "tclog", 0}, { &key_file_trg, "trigger_name", 0}, { &key_file_trn, "trigger", 0}, - { &key_file_init, "init", 0} + { &key_file_init, "init", 0}, + { &key_file_binlog_state, "binlog_state", 0} }; /** @@ -1109,7 +1156,7 @@ private: void Buffered_logs::init() { - init_alloc_root(&m_root, 1024, 0); + init_alloc_root(&m_root, 1024, 0, MYF(0)); } void Buffered_logs::cleanup() @@ -1267,6 +1314,9 @@ struct st_VioSSLFd *ssl_acceptor_fd; */ uint connection_count= 0, extra_connection_count= 0; +my_bool opt_gtid_strict_mode= FALSE; + + /* Function declarations */ pthread_handler_t signal_hand(void *arg); @@ -1461,8 +1511,21 @@ static void close_connections(void) Events::deinit(); end_slave(); - /* Give threads time to die. */ - for (int i= 0; thread_count && i < 100; i++) + /* + Give threads time to die. + + In 5.5, this was waiting 100 rounds @ 20 milliseconds/round, so as little + as 2 seconds, depending on thread scheduling. + + From 10.0, we increase this to 1000 rounds / 20 seconds. The rationale is + that on a server with heavy I/O load, it is quite possible for eg. an + fsync() of the binlog or whatever to cause something like LOCK_log to be + held for more than 2 seconds. We do not want to force kill threads in + such cases, if it can be avoided. Note that normally, the wait will be + much smaller than even 2 seconds, this is only a safety fallback against + stuck threads so server shutdown is not held up forever. + */ + for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++) my_sleep(20000); /* @@ -1756,11 +1819,14 @@ extern "C" void unireg_abort(int exit_code) static void mysqld_exit(int exit_code) { + DBUG_ENTER("mysqld_exit"); /* Important note: we wait for the signal thread to end, but if a kill -15 signal was sent, the signal thread did spawn the kill_server_thread thread, which is running concurrently. */ + rpl_deinit_gtid_waiting(); + rpl_deinit_gtid_slave_state(); wait_for_signal_thread_to_end(); mysql_audit_finalize(); clean_up_mutexes(); @@ -1768,6 +1834,7 @@ static void mysqld_exit(int exit_code) my_end((opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0)); #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE shutdown_performance_schema(); // we do it as late as possible + //DBUG_LEAVE; #endif exit(exit_code); /* purecov: inspected */ } @@ -1780,7 +1847,12 @@ void clean_up(bool print_message) if (cleanup_done++) return; /* purecov: inspected */ - close_active_mi(); +#ifdef HAVE_REPLICATION + // We must call end_slave() as clean_up may have been called during startup + end_slave(); + if (use_slave_mask) + bitmap_free(&slave_error_mask); +#endif stop_handle_manager(); release_ddl_log(); @@ -1795,21 +1867,17 @@ void clean_up(bool print_message) injector::free_instance(); mysql_bin_log.cleanup(); -#ifdef HAVE_REPLICATION - if (use_slave_mask) - bitmap_free(&slave_error_mask); -#endif my_tz_free(); my_dboptions_cache_free(); ignore_db_dirs_free(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS servers_free(1); +#ifndef NO_EMBEDDED_ACCESS_CHECKS acl_free(1); grant_free(); #endif query_cache_destroy(); hostname_cache_free(); - item_user_lock_free(); + item_func_sleep_free(); lex_free(); /* Free some memory */ item_create_cleanup(); if (!opt_noacl) @@ -1849,12 +1917,11 @@ void clean_up(bool print_message) #endif my_uuid_end(); delete binlog_filter; - delete rpl_filter; + delete global_rpl_filter; end_ssl(); #ifndef EMBEDDED_LIBRARY vio_end(); #endif /*!EMBEDDED_LIBRARY*/ - my_regex_end(); #if defined(ENABLED_DEBUG_SYNC) /* End the debug sync facility. See debug_sync.cc. */ debug_sync_end(); @@ -1875,6 +1942,9 @@ void clean_up(bool print_message) sys_var_end(); my_atomic_rwlock_destroy(&global_query_id_lock); my_atomic_rwlock_destroy(&thread_running_lock); + my_atomic_rwlock_destroy(&thread_count_lock); + my_atomic_rwlock_destroy(&statistics_lock); + my_atomic_rwlock_destroy(&slave_executed_entries_lock); free_charsets(); mysql_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("got thread count lock")); @@ -1918,6 +1988,7 @@ static void clean_up_mutexes() DBUG_ENTER("clean_up_mutexes"); mysql_rwlock_destroy(&LOCK_grant); mysql_mutex_destroy(&LOCK_thread_count); + mysql_mutex_destroy(&LOCK_thread_cache); mysql_mutex_destroy(&LOCK_status); mysql_mutex_destroy(&LOCK_delayed_insert); mysql_mutex_destroy(&LOCK_delayed_status); @@ -1955,6 +2026,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); mysql_mutex_destroy(&LOCK_prepare_ordered); + mysql_cond_destroy(&COND_prepare_ordered); mysql_mutex_destroy(&LOCK_commit_ordered); DBUG_VOID_RETURN; } @@ -2418,7 +2490,7 @@ void close_connection(THD *thd, uint sql_errno) { sleep(0); /* Workaround to avoid tailcall optimisation */ } - MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, sql_errno); + mysql_audit_notify_connection_disconnect(thd, sql_errno); DBUG_VOID_RETURN; } #endif /* EMBEDDED_LIBRARY */ @@ -2465,6 +2537,28 @@ void dec_connection_count(THD *thd) /* + Delete THD and decrement thread counters, including thread_running +*/ + +void delete_running_thd(THD *thd) +{ + mysql_mutex_lock(&LOCK_thread_count); + thd->unlink(); + mysql_mutex_unlock(&LOCK_thread_count); + + delete thd; + dec_thread_running(); + thread_safe_decrement32(&thread_count, &thread_count_lock); + if (!thread_count) + { + mysql_mutex_lock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + } +} + + +/* Unlink thd from global list of available connections and free thd SYNOPSIS @@ -2488,7 +2582,6 @@ void unlink_thd(THD *thd) mysql_mutex_unlock(&LOCK_status); mysql_mutex_lock(&LOCK_thread_count); - thread_count--; thd->unlink(); /* Used by binlog_reset_master. It would be cleaner to use @@ -2499,6 +2592,8 @@ void unlink_thd(THD *thd) mysql_mutex_unlock(&LOCK_thread_count); delete thd; + thread_safe_decrement32(&thread_count, &thread_count_lock); + DBUG_VOID_RETURN; } @@ -2510,7 +2605,7 @@ void unlink_thd(THD *thd) cache_thread() NOTES - LOCK_thread_count has to be locked + LOCK_thread_cache is used to protect the cache variables RETURN 0 Thread was not put in cache @@ -2521,7 +2616,9 @@ void unlink_thd(THD *thd) static bool cache_thread() { - mysql_mutex_assert_owner(&LOCK_thread_count); + DBUG_ENTER("cache_thread"); + + mysql_mutex_lock(&LOCK_thread_cache); if (cached_thread_count < thread_cache_size && ! abort_loop && !kill_cached_threads) { @@ -2539,7 +2636,7 @@ static bool cache_thread() #endif while (!abort_loop && ! wake_thread && ! kill_cached_threads) - mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count); + mysql_cond_wait(&COND_thread_cache, &LOCK_thread_cache); cached_thread_count--; if (kill_cached_threads) mysql_cond_signal(&COND_flush_thread_cache); @@ -2548,6 +2645,8 @@ static bool cache_thread() THD *thd; wake_thread--; thd= thread_cache.get(); + mysql_mutex_unlock(&LOCK_thread_cache); + thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); @@ -2573,11 +2672,16 @@ static bool cache_thread() thd->mysys_var->abort= 0; thd->thr_create_utime= microsecond_interval_timer(); thd->start_utime= thd->thr_create_utime; + + /* Link thd into list of all active threads (THD's) */ + mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); - return(1); + mysql_mutex_unlock(&LOCK_thread_count); + DBUG_RETURN(1); } } - return(0); + mysql_mutex_unlock(&LOCK_thread_cache); + DBUG_RETURN(0); } @@ -2605,24 +2709,28 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_ENTER("one_thread_per_connection_end"); unlink_thd(thd); /* Mark that current_thd is not valid anymore */ - my_pthread_setspecific_ptr(THR_THD, 0); - if (put_in_cache) + set_current_thd(0); + if (put_in_cache && cache_thread()) + DBUG_RETURN(0); // Thread is reused + + /* + It's safe to check for thread_count outside of the mutex + as we are only interested to see if it was counted to 0 by the + above unlink_thd() call. We should only signal COND_thread_count if + thread_count is likely to be 0. (false positives are ok) + */ + if (!thread_count) { mysql_mutex_lock(&LOCK_thread_count); - put_in_cache= cache_thread(); + DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); + mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); - if (put_in_cache) - DBUG_RETURN(0); // Thread is reused } - - /* It's safe to broadcast outside a lock (COND... is not deleted here) */ - DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); DBUG_LEAVE; // Must match DBUG_ENTER() #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) ERR_remove_state(0); #endif my_thread_end(); - mysql_cond_broadcast(&COND_thread_count); pthread_exit(0); return 0; // Avoid compiler warnings @@ -2631,15 +2739,17 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) void flush_thread_cache() { - mysql_mutex_lock(&LOCK_thread_count); + DBUG_ENTER("flush_thread_cache"); + mysql_mutex_lock(&LOCK_thread_cache); kill_cached_threads++; while (cached_thread_count) { mysql_cond_broadcast(&COND_thread_cache); - mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count); + mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache); } kill_cached_threads--; - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_cache); + DBUG_VOID_RETURN; } @@ -3158,9 +3268,9 @@ void my_message_sql(uint error, const char *str, myf MyFlags) THD *thd= current_thd; MYSQL_ERROR::enum_warning_level level; sql_print_message_func func; - DBUG_ENTER("my_message_sql"); - DBUG_PRINT("error", ("error: %u message: '%s' Flag: %d", error, str, MyFlags)); + DBUG_PRINT("error", ("error: %u message: '%s' Flag: %lu", error, str, + MyFlags)); DBUG_ASSERT(str != NULL); DBUG_ASSERT(error != 0); @@ -3199,7 +3309,6 @@ void my_message_sql(uint error, const char *str, myf MyFlags) } -#ifndef EMBEDDED_LIBRARY extern "C" void *my_str_malloc_mysqld(size_t size); extern "C" void my_str_free_mysqld(void *ptr); @@ -3213,7 +3322,6 @@ void my_str_free_mysqld(void *ptr) { my_free(ptr); } -#endif /* EMBEDDED_LIBRARY */ #ifdef __WIN__ @@ -3245,24 +3353,56 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); /** This function is used to check for stack overrun for pathological cases of regular expressions and 'like' expressions. - The call to current_thd is quite expensive, so we try to avoid it - for the normal cases. +*/ +extern "C" int +check_enough_stack_size_slow() +{ + uchar stack_top; + THD *my_thd= current_thd; + if (my_thd != NULL) + return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top); + return 0; +} + + +/* + The call to current_thd in check_enough_stack_size_slow is quite expensive, + so we try to avoid it for the normal cases. The size of each stack frame for the wildcmp() routines is ~128 bytes, so checking *every* recursive call is not necessary. */ extern "C" int check_enough_stack_size(int recurse_level) { - uchar stack_top; if (recurse_level % 16 != 0) return 0; + return check_enough_stack_size_slow(); +} +#endif - THD *my_thd= current_thd; - if (my_thd != NULL) - return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top); - return 0; + + +/* + Initialize my_str_malloc() and my_str_free() +*/ +static void init_libstrings() +{ + my_str_malloc= &my_str_malloc_mysqld; + my_str_free= &my_str_free_mysqld; +#ifndef EMBEDDED_LIBRARY + my_string_stack_guard= check_enough_stack_size; +#endif } + + +static void init_pcre() +{ + pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld; + pcre_free= pcre_stack_free= my_str_free_mysqld; +#ifndef EMBEDDED_LIBRARY + pcre_stack_guard= check_enough_stack_size_slow; #endif +} /** @@ -3320,6 +3460,7 @@ SHOW_VAR com_status_vars[]= { {"create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS}, {"create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS}, {"create_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS}, + {"create_role", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_ROLE]), SHOW_LONG_STATUS}, {"create_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS}, {"create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS}, {"create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS}, @@ -3335,6 +3476,7 @@ SHOW_VAR com_status_vars[]= { {"drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS}, {"drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS}, {"drop_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS}, + {"drop_role", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_ROLE]), SHOW_LONG_STATUS}, {"drop_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS}, {"drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS}, {"drop_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS}, @@ -3344,6 +3486,7 @@ SHOW_VAR com_status_vars[]= { {"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS}, {"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS}, {"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS}, + {"grant_role", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT_ROLE]), SHOW_LONG_STATUS}, {"ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS}, {"ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS}, {"ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS}, @@ -3369,6 +3512,7 @@ SHOW_VAR com_status_vars[]= { {"resignal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS}, {"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS}, {"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS}, + {"revoke_role", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ROLE]), SHOW_LONG_STATUS}, {"rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS}, {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS}, {"savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS}, @@ -3393,6 +3537,7 @@ SHOW_VAR com_status_vars[]= { {"show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS}, {"show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS}, {"show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS}, + {"show_explain", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EXPLAIN]), SHOW_LONG_STATUS}, {"show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS}, #ifndef DBUG_OFF {"show_function_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS}, @@ -3424,9 +3569,10 @@ SHOW_VAR com_status_vars[]= { {"show_user_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS}, {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS}, {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS}, + {"shutdown", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHUTDOWN]), SHOW_LONG_STATUS}, {"signal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS}, - {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, - {"slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, + {"start_all_slaves", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_START]), SHOW_LONG_STATUS}, + {"start_slave", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, {"stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS}, {"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS}, {"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS}, @@ -3434,6 +3580,8 @@ SHOW_VAR com_status_vars[]= { {"stmt_reprepare", (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS}, {"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS}, {"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS}, + {"stop_all_slaves", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_STOP]), SHOW_LONG_STATUS}, + {"stop_slave", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, {"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS}, {"uninstall_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS}, {"unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS}, @@ -3448,21 +3596,89 @@ SHOW_VAR com_status_vars[]= { {NullS, NullS, SHOW_LONG} }; +#ifdef SAFEMALLOC +/* + Return the id for the current THD, to allow safemalloc to associate + the memory with the right id. +*/ + +extern "C" my_thread_id mariadb_dbug_id() +{ + THD *thd; + if ((thd= current_thd)) + { + return thd->thread_id; + } + return my_thread_dbug_id(); +} +#endif /* SAFEMALLOC */ + +/* Thread Mem Usage By P.Linux */ +extern "C" { +static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) +{ + /* If thread specific memory */ + if (is_thread_specific) + { + THD *thd= current_thd; + if (mysqld_server_initialized || thd) + { + /* + THD may not be set if we are called from my_net_init() before THD + thread has started. + However, this should never happen, so better to assert and + fix this. + */ + DBUG_ASSERT(thd); + if (thd) + { + DBUG_PRINT("info", ("memory_used: %lld size: %lld", + (longlong) thd->status_var.memory_used, size)); + thd->status_var.memory_used+= size; + DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0); + } + } + } + // workaround for gcc 4.2.4-1ubuntu4 -fPIE (from DEB_BUILD_HARDENING=1) + int64 volatile * volatile ptr=&global_status_var.memory_used; + my_atomic_add64(ptr, size); +} +} + + +/* + Init common variables +*/ + static int init_common_variables() { umask(((~my_umask) & 0666)); my_decimal_set_zero(&decimal_zero); // set decimal_zero constant; + if (pthread_key_create(&THR_THD,NULL) || + pthread_key_create(&THR_MALLOC,NULL)) + { + sql_print_error("Can't create thread-keys"); + return 1; + } + + set_current_thd(0); + set_malloc_size_cb(my_malloc_size_cb_func); + + init_libstrings(); tzset(); // Set tzname sf_leaking_memory= 0; // no memory leaks from now on +#ifdef SAFEMALLOC + sf_malloc_dbug_id= mariadb_dbug_id; +#endif max_system_variables.pseudo_thread_id= (ulong)~0; server_start_time= flush_status_time= my_time(0); - rpl_filter= new Rpl_filter; + global_rpl_filter= new Rpl_filter; binlog_filter= new Rpl_filter; - if (!rpl_filter || !binlog_filter) + if (!global_rpl_filter || !binlog_filter) { sql_perror("Could not allocate replication and binlog filters"); return 1; @@ -3752,12 +3968,7 @@ static int init_common_variables() if (item_create_init()) return 1; item_init(); -#ifndef EMBEDDED_LIBRARY - my_regex_init(&my_charset_latin1, check_enough_stack_size); - my_string_stack_guard= check_enough_stack_size; -#else - my_regex_init(&my_charset_latin1, NULL); -#endif + init_pcre(); /* Process a comma-separated character set list and choose the first available character set. This is mostly for @@ -3916,7 +4127,9 @@ You should consider changing lower_case_table_names to 1 or 2", static int init_thread_environment() { + DBUG_ENTER("init_thread_environment"); mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_delayed_insert, &LOCK_delayed_insert, MY_MUTEX_INIT_FAST); @@ -3929,6 +4142,7 @@ static int init_thread_environment() mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_global_system_variables, &LOCK_global_system_variables, MY_MUTEX_INIT_FAST); + mysql_mutex_record_order(&LOCK_active_mi, &LOCK_global_system_variables); mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash, &LOCK_system_variables_hash); mysql_mutex_init(key_LOCK_prepared_stmt_count, @@ -3948,6 +4162,7 @@ static int init_thread_environment() &LOCK_global_index_stats, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_prepare_ordered, &LOCK_prepare_ordered, MY_MUTEX_INIT_SLOW); + mysql_cond_init(key_COND_prepare_ordered, &COND_prepare_ordered, NULL); mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered, MY_MUTEX_INIT_SLOW); @@ -3983,19 +4198,19 @@ static int init_thread_environment() #ifdef HAVE_EVENT_SCHEDULER Events::init_mutexes(); #endif + init_show_explain_psi_keys(); /* Parameter for threads created for connections */ (void) pthread_attr_init(&connection_attrib); (void) pthread_attr_setdetachstate(&connection_attrib, PTHREAD_CREATE_DETACHED); pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM); - if (pthread_key_create(&THR_THD,NULL) || - pthread_key_create(&THR_MALLOC,NULL)) - { - sql_print_error("Can't create thread-keys"); - return 1; - } - return 0; +#ifdef HAVE_REPLICATION + rpl_init_gtid_slave_state(); + rpl_init_gtid_waiting(); +#endif + + DBUG_RETURN(0); } @@ -4430,7 +4645,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); plugin_ref plugin; handlerton *hton; if ((plugin= ha_resolve_by_name(0, &name))) - hton= plugin_data(plugin, handlerton*); + hton= plugin_hton(plugin); else { sql_print_error("Unknown/unsupported storage engine: %s", @@ -4488,7 +4703,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); } if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, - WRITE_CACHE, 0, max_binlog_size, 0, TRUE)) + WRITE_CACHE, max_binlog_size, 0, TRUE)) unireg_abort(1); #ifdef HAVE_REPLICATION @@ -4530,6 +4745,8 @@ a file name for --log-bin-index option", opt_binlog_index_name); init_update_queries(); init_global_user_stats(); init_global_client_stats(); + if (!opt_bootstrap) + servers_init(0); DBUG_RETURN(0); } @@ -4705,6 +4922,7 @@ static void test_lc_time_sz() } #endif//DBUG_OFF + #ifdef __WIN__ int win_main(int argc, char **argv) #else @@ -4717,6 +4935,8 @@ int mysqld_main(int argc, char **argv) */ my_progname= argv[0]; sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early + mysqld_server_started= mysqld_server_initialized= 0; + #ifdef HAVE_NPTL ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0); #endif @@ -4759,7 +4979,7 @@ int mysqld_main(int argc, char **argv) my_getopt_skip_unknown= TRUE; /* prepare all_early_options array */ - my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25); + my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25, MYF(0)); sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY); add_terminator(&all_early_options); @@ -4912,9 +5132,9 @@ int mysqld_main(int argc, char **argv) set_user(mysqld_user, user_info); } - if (opt_bin_log && !server_id) + if (opt_bin_log && !global_system_variables.server_id) { - server_id= 1; + global_system_variables.server_id= ::server_id= 1; #ifdef EXTRA_DEBUG sql_print_warning("You have enabled the binary log, but you haven't set " "server-id to a non-zero value: we force server id to 1; " @@ -4948,12 +5168,6 @@ int mysqld_main(int argc, char **argv) #endif /* - Initialize my_str_malloc() and my_str_free() - */ - my_str_malloc= &my_str_malloc_mysqld; - my_str_free= &my_str_free_mysqld; - - /* init signals & alarm After this we can't quit by a simple unireg_abort */ @@ -4977,9 +5191,6 @@ int mysqld_main(int argc, char **argv) if (!opt_noacl) (void) grant_init(); - if (!opt_bootstrap) - servers_init(0); - if (!opt_noacl) { #ifdef HAVE_DLOPEN @@ -4992,16 +5203,6 @@ int mysqld_main(int argc, char **argv) opt_skip_slave_start= 1; binlog_unsafe_map_init(); - /* - init_slave() must be called after the thread keys are created. - Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other - places) assume that active_mi != 0, so let's fail if it's 0 (out of - memory); a message has already been printed. - */ - if (init_slave() && !active_mi) - { - unireg_abort(1); - } #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE initialize_performance_schema_acl(opt_bootstrap); @@ -5019,6 +5220,12 @@ int mysqld_main(int argc, char **argv) execute_ddl_log_recovery(); + /* + We must have LOCK_open before LOCK_global_system_variables because + LOCK_open is held while sql_plugin.c::intern_sys_var_ptr() is called. + */ + mysql_mutex_record_order(&LOCK_open, &LOCK_global_system_variables); + if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); @@ -5034,21 +5241,33 @@ int mysqld_main(int argc, char **argv) exit(0); } } + + /* It's now safe to use thread specific memory */ + mysqld_server_initialized= 1; + + create_shutdown_thread(); + start_handle_manager(); + + /* Copy default global rpl_filter to global_rpl_filter */ + copy_filter_setting(global_rpl_filter, get_or_create_rpl_filter("", 0)); + + /* + init_slave() must be called after the thread keys are created. + Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other + places) assume that active_mi != 0, so let's fail if it's 0 (out of + memory); a message has already been printed. + */ + if (init_slave() && !active_mi) + { + unireg_abort(1); + } + if (opt_init_file && *opt_init_file) { if (read_init_file(opt_init_file)) unireg_abort(1); } - /* - We must have LOCK_open before LOCK_global_system_variables because - LOCK_open is hold while sql_plugin.c::intern_sys_var_ptr() is called. - */ - mysql_mutex_record_order(&LOCK_open, &LOCK_global_system_variables); - - create_shutdown_thread(); - start_handle_manager(); - sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version, ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port), @@ -5058,7 +5277,6 @@ int mysqld_main(int argc, char **argv) Service.SetRunning(); #endif - /* Signal threads waiting for server to be started */ mysql_mutex_lock(&LOCK_server_started); mysqld_server_started= 1; @@ -5346,11 +5564,11 @@ static void bootstrap(MYSQL_FILE *file) THD *thd= new THD; thd->bootstrap=1; - my_net_init(&thd->net,(st_vio*) 0); + my_net_init(&thd->net,(st_vio*) 0, MYF(0)); thd->max_client_packet_length= thd->net.max_packet; thd->security_ctx->master_access= ~(ulong)0; thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - thread_count++; + thread_count++; // Safe as only one thread running in_bootstrap= TRUE; bootstrap_file=file; @@ -5434,55 +5652,69 @@ void handle_connection_in_main_thread(THD *thd) void create_thread_to_handle_connection(THD *thd) { + DBUG_ENTER("create_thread_to_handle_connection"); + mysql_mutex_assert_owner(&LOCK_thread_count); + + /* Check if we can get thread from the cache */ if (cached_thread_count > wake_thread) { - /* Get thread from cache */ - thread_cache.push_back(thd); - wake_thread++; - mysql_cond_signal(&COND_thread_cache); + mysql_mutex_lock(&LOCK_thread_cache); + /* Recheck condition when we have the lock */ + if (cached_thread_count > wake_thread) + { + mysql_mutex_unlock(&LOCK_thread_count); + /* Get thread from cache */ + thread_cache.push_back(thd); + wake_thread++; + mysql_cond_signal(&COND_thread_cache); + mysql_mutex_unlock(&LOCK_thread_cache); + DBUG_PRINT("info",("Thread created")); + DBUG_VOID_RETURN; + } + mysql_mutex_unlock(&LOCK_thread_cache); } - else + + char error_message_buff[MYSQL_ERRMSG_SIZE]; + /* Create new thread to handle connection */ + int error; + thread_created++; + threads.append(thd); + DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); + thd->prior_thr_create_utime= microsecond_interval_timer(); + if ((error= mysql_thread_create(key_thread_one_connection, + &thd->real_id, &connection_attrib, + handle_one_connection, + (void*) thd))) { - char error_message_buff[MYSQL_ERRMSG_SIZE]; - /* Create new thread to handle connection */ - int error; - thread_created++; - threads.append(thd); - DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); - thd->prior_thr_create_utime= microsecond_interval_timer(); - if ((error= mysql_thread_create(key_thread_one_connection, - &thd->real_id, &connection_attrib, - handle_one_connection, - (void*) thd))) - { - /* purecov: begin inspected */ - DBUG_PRINT("error", - ("Can't create thread to handle request (error %d)", - error)); + /* purecov: begin inspected */ + DBUG_PRINT("error", + ("Can't create thread to handle request (error %d)", + error)); + thd->killed= KILL_CONNECTION; // Safety + mysql_mutex_unlock(&LOCK_thread_count); - thread_count--; - thd->killed= KILL_CONNECTION; // Safety - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_connection_count); + (*thd->scheduler->connection_count)--; + mysql_mutex_unlock(&LOCK_connection_count); - mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; - mysql_mutex_unlock(&LOCK_connection_count); + statistic_increment(aborted_connects,&LOCK_status); + /* Can't use my_error() since store_globals has not been called. */ + my_snprintf(error_message_buff, sizeof(error_message_buff), + ER_THD(thd, ER_CANT_CREATE_THREAD), error); + net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); + close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - /* Can't use my_error() since store_globals has not been called. */ - my_snprintf(error_message_buff, sizeof(error_message_buff), - ER_THD(thd, ER_CANT_CREATE_THREAD), error); - net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); - close_connection(thd, ER_OUT_OF_RESOURCES); - mysql_mutex_lock(&LOCK_thread_count); - delete thd; - mysql_mutex_unlock(&LOCK_thread_count); - return; - /* purecov: end */ - } + mysql_mutex_lock(&LOCK_thread_count); + thd->unlink(); + mysql_mutex_unlock(&LOCK_thread_count); + delete thd; + thread_safe_decrement32(&thread_count, &thread_count_lock); + return; + /* purecov: end */ } mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("Thread created")); + DBUG_VOID_RETURN; } @@ -5529,10 +5761,10 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); - /* Start a new thread to handle connection. */ + thread_safe_increment32(&thread_count, &thread_count_lock); + /* Start a new thread to handle connection. */ mysql_mutex_lock(&LOCK_thread_count); - /* The initialization of thread_id is done in create_embedded_thd() for the embedded library. @@ -5540,8 +5772,6 @@ static void create_new_thread(THD *thd) */ thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - thread_count++; - MYSQL_CALLBACK(thd->scheduler, add_connection, (thd)); DBUG_VOID_RETURN; @@ -5749,35 +5979,24 @@ void handle_connections_sockets() } #endif /* HAVE_LIBWRAP */ - { - size_socket dummyLen; - struct sockaddr_storage dummy; - dummyLen = sizeof(dummy); - if ( getsockname(new_sock,(struct sockaddr *)&dummy, - (SOCKET_SIZE_TYPE *)&dummyLen) < 0 ) - { - sql_perror("Error on new connection socket"); - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) closesocket(new_sock); - continue; - } - } - /* ** Don't allow too many connections */ + DBUG_PRINT("info", ("Creating THD for new connection")); if (!(thd= new THD)) { (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } + /* Set to get io buffers to be part of THD */ + set_current_thd(thd); if (!(vio_tmp=vio_new(new_sock, sock == unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, sock == unix_sock ? VIO_LOCALHOST: 0)) || - my_net_init(&thd->net,vio_tmp)) + my_net_init(&thd->net, vio_tmp, MYF(MY_THREAD_SPECIFIC))) { /* Only delete the temporary vio if we didn't already attach it to the @@ -5792,6 +6011,7 @@ void handle_connections_sockets() (void) closesocket(new_sock); } delete thd; + set_current_thd(0); continue; } if (sock == unix_sock) @@ -5803,6 +6023,7 @@ void handle_connections_sockets() thd->scheduler= extra_thread_scheduler; } create_new_thread(thd); + set_current_thd(0); } DBUG_VOID_RETURN; } @@ -5896,16 +6117,19 @@ pthread_handler_t handle_connections_namedpipes(void *arg) CloseHandle(hConnectedPipe); continue; } + set_current_thd(thd); if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || - my_net_init(&thd->net, thd->net.vio)) + my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { close_connection(thd, ER_OUT_OF_RESOURCES); delete thd; + set_current_thd(0); continue; } /* Host is unknown */ thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); create_new_thread(thd); + set_current_thd(0); } CloseHandle(connectOverlapped.hEvent); DBUG_LEAVE; @@ -6085,6 +6309,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) errmsg= "Could not set client to read mode"; goto errorconn; } + set_current_thd(thd); if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map, handle_client_map, event_client_wrote, @@ -6092,7 +6317,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) event_server_wrote, event_server_read, event_conn_closed)) || - my_net_init(&thd->net, thd->net.vio)) + my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { close_connection(thd, ER_OUT_OF_RESOURCES); errmsg= 0; @@ -6101,6 +6326,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ create_new_thread(thd); connect_number++; + set_current_thd(thd); continue; errorconn: @@ -6128,6 +6354,7 @@ errorconn: CloseHandle(event_conn_closed); delete thd; } + set_current_thd(0); /* End shared memory handling */ error: @@ -6165,6 +6392,7 @@ error: */ struct my_option my_long_options[]= + { {"help", '?', "Display this help and exit.", &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, @@ -6442,28 +6670,28 @@ struct my_option my_long_options[]= "while having selected a different or no database. If you need cross " "database updates to work, make sure you have 3.23.28 or later, and use " "replicate-wild-do-table=db_name.%.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-table", OPT_REPLICATE_DO_TABLE, "Tells the slave thread to restrict replication to the specified table. " "To specify more than one table, use the directive multiple times, once " "for each table. This will work for cross-database updates, in contrast " - "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "to replicate-do-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB, "Tells the slave thread to not replicate to the specified database. To " "specify more than one database to ignore, use the directive multiple " "times, once for each database. This option will not work if you use " "cross database updates. If you need cross database updates to work, " "make sure you have 3.23.28 or later, and use replicate-wild-ignore-" - "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "table=db_name.%. ", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE, "Tells the slave thread to not replicate to the specified table. To specify " "more than one table to ignore, use the directive multiple times, once for " "each table. This will work for cross-database updates, in contrast to " - "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "replicate-ignore-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, "Updates to a database with a different name than the original. Example: " "replicate-rewrite-db=master_db_name->slave_db_name.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"replicate-same-server-id", 0, "In replication, if set to 1, do not skip events having our server id. " @@ -6479,7 +6707,7 @@ struct my_option my_long_options[]= "database updates. Example: replicate-wild-do-table=foo%.bar% will " "replicate only updates to tables in all databases that start with foo " "and whose table names start with bar.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE, "Tells the slave thread to not replicate to the tables that match the " "given wildcard pattern. To specify more than one table to ignore, use " @@ -6487,7 +6715,7 @@ struct my_option my_long_options[]= "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% " "will not do updates to tables in databases that start with foo and whose " "table names start with bar.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing). Deprecated.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"safe-user-create", 0, @@ -6630,66 +6858,76 @@ static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff) static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; + bool tmp; + LINT_INIT(tmp); + var->type= SHOW_MY_BOOL; - mysql_mutex_lock(&LOCK_active_mi); var->value= buff; - *((my_bool *)buff)= (my_bool) (active_mi && - active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT && - active_mi->rli.slave_running); - mysql_mutex_unlock(&LOCK_active_mi); - return 0; -} - -static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff) -{ - /* - TODO: with multimaster, have one such counter per line in - SHOW SLAVE STATUS, and have the sum over all lines here. - */ + mysql_mutex_unlock(&LOCK_status); mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_LONG; - var->value= buff; - mysql_mutex_lock(&active_mi->rli.data_lock); - *((long *)buff)= (long)active_mi->rli.retried_trans; - mysql_mutex_unlock(&active_mi->rli.data_lock); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT && + mi->rli.slave_running); + mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_status); + if (mi) + *((my_bool *)buff)= tmp; else var->type= SHOW_UNDEF; - mysql_mutex_unlock(&LOCK_active_mi); return 0; } + static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; + longlong tmp; + LINT_INIT(tmp); + + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_unlock(&LOCK_status); mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_LONGLONG; - var->value= buff; - mysql_mutex_lock(&active_mi->rli.data_lock); - *((longlong *)buff)= active_mi->received_heartbeats; - mysql_mutex_unlock(&active_mi->rli.data_lock); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + tmp= mi->received_heartbeats; + mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_status); + if (mi) + *((longlong *)buff)= tmp; else var->type= SHOW_UNDEF; - mysql_mutex_unlock(&LOCK_active_mi); return 0; } + static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) { + Master_info *mi; + float tmp; + LINT_INIT(tmp); + + var->type= SHOW_CHAR; + var->value= buff; + mysql_mutex_unlock(&LOCK_status); mysql_mutex_lock(&LOCK_active_mi); - if (active_mi) - { - var->type= SHOW_CHAR; - var->value= buff; - sprintf(buff, "%.3f", active_mi->heartbeat_period); - } + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + MYSQL_ERROR::WARN_LEVEL_NOTE); + if (mi) + tmp= mi->heartbeat_period; + mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_status); + if (mi) + sprintf(buff, "%.3f", tmp); else var->type= SHOW_UNDEF; - mysql_mutex_unlock(&LOCK_active_mi); return 0; } @@ -7020,6 +7258,42 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff) return 0; } +#ifndef DBUG_OFF +static int debug_status_func(THD *thd, SHOW_VAR *var, char *buff) +{ +#define add_var(X,Y,Z) \ + v->name= X; \ + v->value= (char*)Y; \ + v->type= Z; \ + v++; + + var->type= SHOW_ARRAY; + var->value= buff; + + SHOW_VAR *v= (SHOW_VAR *)buff; + + if (_db_keyword_(0, "role_merge_stats", 1)) + { + static SHOW_VAR roles[]= { + {"global", (char*) &role_global_merges, SHOW_ULONG}, + {"db", (char*) &role_db_merges, SHOW_ULONG}, + {"table", (char*) &role_table_merges, SHOW_ULONG}, + {"column", (char*) &role_column_merges, SHOW_ULONG}, + {"routine", (char*) &role_routine_merges, SHOW_ULONG}, + {NullS, NullS, SHOW_LONG} + }; + + add_var("role_merges", roles, SHOW_ARRAY); + } + + v->name= 0; + +#undef add_var + + return 0; +} +#endif + #ifdef HAVE_POOL_OF_THREADS int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff) { @@ -7047,12 +7321,15 @@ SHOW_VAR status_vars[]= { {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS}, {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, {"Com", (char*) com_status_vars, SHOW_ARRAY}, - {"Compression", (char*) &show_net_compression, SHOW_FUNC}, + {"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC}, {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, {"Cpu_time", (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, {"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS}, +#ifndef DBUG_OFF + {"Debug", (char*) &debug_status_func, SHOW_FUNC}, +#endif {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, @@ -7065,8 +7342,8 @@ SHOW_VAR status_vars[]= { {"Feature_locale", (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS}, {"Feature_subquery", (char*) offsetof(STATUS_VAR, feature_subquery), SHOW_LONG_STATUS}, {"Feature_timezone", (char*) offsetof(STATUS_VAR, feature_timezone), SHOW_LONG_STATUS}, - {"Feature_trigger", (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS}, - {"Feature_xml", (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS}, + {"Feature_trigger", (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS}, + {"Feature_xml", (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS}, {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH}, {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, @@ -7074,8 +7351,8 @@ SHOW_VAR status_vars[]= { {"Handler_icp_attempts", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS}, {"Handler_icp_match", (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS}, {"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_mrr_init_count), SHOW_LONG_STATUS}, - {"Handler_mrr_key_refills", (char*) offsetof(STATUS_VAR, ha_mrr_key_refills_count), SHOW_LONG_STATUS}, - {"Handler_mrr_rowid_refills", (char*) offsetof(STATUS_VAR, ha_mrr_rowid_refills_count), SHOW_LONG_STATUS}, + {"Handler_mrr_key_refills", (char*) offsetof(STATUS_VAR, ha_mrr_key_refills_count), SHOW_LONG_STATUS}, + {"Handler_mrr_rowid_refills",(char*) offsetof(STATUS_VAR, ha_mrr_rowid_refills_count), SHOW_LONG_STATUS}, {"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS}, {"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS}, {"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS}, @@ -7095,18 +7372,20 @@ SHOW_VAR status_vars[]= { {"Key", (char*) &show_default_keycache, SHOW_FUNC}, {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, + {"Memory_used", (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, - {"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC}, - {"Open_tables", (char*) &show_open_tables, SHOW_FUNC}, + {"Open_table_definitions", (char*) &show_table_definitions, SHOW_SIMPLE_FUNC}, + {"Open_tables", (char*) &show_open_tables, SHOW_SIMPLE_FUNC}, {"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH}, + {"Opened_plugin_libraries", (char*) &dlopen_count, SHOW_LONG}, {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS}, {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, - {"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS}, - {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC}, - {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS}, + {"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS}, + {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC}, {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS}, + {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS}, {"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS}, #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, @@ -7118,22 +7397,22 @@ SHOW_VAR status_vars[]= { {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH}, {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH}, #endif /*HAVE_QUERY_CACHE*/ - {"Queries", (char*) &show_queries, SHOW_FUNC}, + {"Queries", (char*) &show_queries, SHOW_SIMPLE_FUNC}, {"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS}, #ifdef HAVE_REPLICATION - {"Rpl_status", (char*) &show_rpl_status, SHOW_FUNC}, + {"Rpl_status", (char*) &show_rpl_status, SHOW_SIMPLE_FUNC}, #endif {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS}, {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS}, {"Select_range", (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS}, {"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS}, {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS}, - {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG}, + {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_INT}, #ifdef HAVE_REPLICATION - {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_FUNC}, - {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC}, - {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC}, - {"Slave_running", (char*) &show_slave_running, SHOW_FUNC}, + {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG}, + {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC}, + {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC}, + {"Slave_running", (char*) &show_slave_running, SHOW_SIMPLE_FUNC}, #endif {"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG}, {"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS}, @@ -7143,29 +7422,29 @@ SHOW_VAR status_vars[]= { {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS}, #ifdef HAVE_OPENSSL #ifndef EMBEDDED_LIBRARY - {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC}, - {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC}, - {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC}, - {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_FUNC}, - {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_FUNC}, - {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC}, - {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC}, - {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC}, - {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC}, - {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_FUNC}, - {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC}, - {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC}, - {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC}, - {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC}, - {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC}, - {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC}, - {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC}, - {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC}, - {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_FUNC}, - {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC}, - {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_FUNC}, - {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC}, - {"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC}, + {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_SIMPLE_FUNC}, + {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_SIMPLE_FUNC}, + {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_SIMPLE_FUNC}, + {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC}, + {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC}, + {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_SIMPLE_FUNC}, + {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_SIMPLE_FUNC}, + {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_SIMPLE_FUNC}, + {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC}, + {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_SIMPLE_FUNC}, + {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_SIMPLE_FUNC}, + {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_SIMPLE_FUNC}, + {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_SIMPLE_FUNC}, + {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_SIMPLE_FUNC}, + {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_version", (char*) &show_ssl_get_version, SHOW_SIMPLE_FUNC}, #endif #endif /* HAVE_OPENSSL */ {"Syncs", (char*) &my_sync_count, SHOW_LONG_NOFLUSH}, @@ -7183,16 +7462,16 @@ SHOW_VAR status_vars[]= { {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG}, #endif #ifdef HAVE_POOL_OF_THREADS - {"Threadpool_idle_threads", (char *) &show_threadpool_idle_threads, SHOW_FUNC}, + {"Threadpool_idle_threads", (char *) &show_threadpool_idle_threads, SHOW_SIMPLE_FUNC}, {"Threadpool_threads", (char *) &tp_stats.num_worker_threads, SHOW_INT}, #endif {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH}, {"Threads_connected", (char*) &connection_count, SHOW_INT}, {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, {"Threads_running", (char*) &thread_running, SHOW_INT}, - {"Uptime", (char*) &show_starttime, SHOW_FUNC}, + {"Uptime", (char*) &show_starttime, SHOW_SIMPLE_FUNC}, #ifdef ENABLED_PROFILING - {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC}, + {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC}, #endif {NullS, NullS, SHOW_LONG} }; @@ -7241,7 +7520,7 @@ static int option_cmp(my_option *a, my_option *b) static void print_help() { MEM_ROOT mem_root; - init_alloc_root(&mem_root, 4096, 4096); + init_alloc_root(&mem_root, 4096, 4096, MYF(0)); pop_dynamic(&all_options); sys_var_add_options(&all_options, sys_var::PARSE_EARLY); @@ -7385,10 +7664,14 @@ static int mysql_init_variables(void) protocol_version= PROTOCOL_VERSION; what_to_log= ~ (1L << (uint) COM_TIME); refresh_version= 2L; /* Increments on each reload. 0 and 1 are reserved */ + denied_connections= 0; executed_events= 0; global_query_id= thread_id= 1L; my_atomic_rwlock_init(&global_query_id_lock); my_atomic_rwlock_init(&thread_running_lock); + my_atomic_rwlock_init(&thread_count_lock); + my_atomic_rwlock_init(&statistics_lock); + my_atomic_rwlock_init(slave_executed_entries_lock); strmov(server_version, MYSQL_SERVER_VERSION); threads.empty(); thread_cache.empty(); @@ -7412,6 +7695,7 @@ static int mysql_init_variables(void) relay_log_info_file= (char*) "relay-log.info"; report_user= report_password = report_host= 0; /* TO BE DELETED */ opt_relay_logname= opt_relaylog_index_name= 0; + slave_retried_transactions= 0; /* Variables in libraries */ charsets_dir= 0; @@ -7436,8 +7720,13 @@ static int mysql_init_variables(void) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) have_ssl=SHOW_OPTION_YES; +#if HAVE_YASSL + have_openssl= SHOW_OPTION_NO; +#else + have_openssl= SHOW_OPTION_YES; +#endif #else - have_ssl=SHOW_OPTION_NO; + have_openssl= have_ssl= SHOW_OPTION_NO; #endif #ifdef HAVE_BROKEN_REALPATH have_symlink=SHOW_OPTION_NO; @@ -7555,7 +7844,7 @@ mysqld_get_one_option(int optid, default_collation_name= 0; break; case 'l': - WARN_DEPRECATED(NULL, 7, 0, "--log", "'--general-log'/'--general-log-file'"); + WARN_DEPRECATED(NULL, 10, 1, "--log", "'--general-log'/'--general-log-file'"); opt_log=1; break; case 'h': @@ -7632,12 +7921,12 @@ mysqld_get_one_option(int optid, #ifdef HAVE_REPLICATION case (int)OPT_REPLICATE_IGNORE_DB: { - rpl_filter->add_ignore_db(argument); + cur_rpl_filter->add_ignore_db(argument); break; } case (int)OPT_REPLICATE_DO_DB: { - rpl_filter->add_do_db(argument); + cur_rpl_filter->add_do_db(argument); break; } case (int)OPT_REPLICATE_REWRITE_DB: @@ -7668,7 +7957,7 @@ mysqld_get_one_option(int optid, return 1; } - rpl_filter->add_db_rewrite(key, val); + cur_rpl_filter->add_db_rewrite(key, val); break; } @@ -7684,7 +7973,7 @@ mysqld_get_one_option(int optid, } case (int)OPT_REPLICATE_DO_TABLE: { - if (rpl_filter->add_do_table(argument)) + if (cur_rpl_filter->add_do_table(argument)) { sql_print_error("Could not add do table rule '%s'!\n", argument); return 1; @@ -7693,7 +7982,7 @@ mysqld_get_one_option(int optid, } case (int)OPT_REPLICATE_WILD_DO_TABLE: { - if (rpl_filter->add_wild_do_table(argument)) + if (cur_rpl_filter->add_wild_do_table(argument)) { sql_print_error("Could not add do table rule '%s'!\n", argument); return 1; @@ -7702,7 +7991,7 @@ mysqld_get_one_option(int optid, } case (int)OPT_REPLICATE_WILD_IGNORE_TABLE: { - if (rpl_filter->add_wild_ignore_table(argument)) + if (cur_rpl_filter->add_wild_ignore_table(argument)) { sql_print_error("Could not add ignore table rule '%s'!\n", argument); return 1; @@ -7711,7 +8000,7 @@ mysqld_get_one_option(int optid, } case (int)OPT_REPLICATE_IGNORE_TABLE: { - if (rpl_filter->add_ignore_table(argument)) + if (cur_rpl_filter->add_ignore_table(argument)) { sql_print_error("Could not add ignore table rule '%s'!\n", argument); return 1; @@ -7720,7 +8009,7 @@ mysqld_get_one_option(int optid, } #endif /* HAVE_REPLICATION */ case (int) OPT_SLOW_QUERY_LOG: - WARN_DEPRECATED(NULL, 7, 0, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'"); + WARN_DEPRECATED(NULL, 10, 1, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'"); opt_slow_log= 1; break; case (int) OPT_SAFE: @@ -7737,7 +8026,7 @@ mysqld_get_one_option(int optid, case (int) OPT_SKIP_PRIOR: opt_specialflag|= SPECIAL_NO_PRIOR; sql_print_warning("The --skip-thread-priority startup option is deprecated " - "and will be removed in MySQL 7.0. This option has no effect " + "and will be removed in MySQL 11.0. This option has no effect " "as the implied behavior is already the default."); break; case (int) OPT_SKIP_HOST_CACHE: @@ -7759,6 +8048,7 @@ mysqld_get_one_option(int optid, break; case OPT_SERVER_ID: server_id_supplied = 1; + ::server_id= global_system_variables.server_id; break; case OPT_ONE_THREAD: thread_handling= SCHEDULER_NO_THREADS; @@ -7831,7 +8121,7 @@ mysqld_get_one_option(int optid, C_MODE_START static void* -mysql_getopt_value(const char *keyname, uint key_length, +mysql_getopt_value(const char *name, uint length, const struct my_option *option, int *error) { if (error) @@ -7844,7 +8134,7 @@ mysql_getopt_value(const char *keyname, uint key_length, case OPT_KEY_CACHE_PARTITIONS: { KEY_CACHE *key_cache; - if (!(key_cache= get_or_create_key_cache(keyname, key_length))) + if (!(key_cache= get_or_create_key_cache(name, length))) { if (error) *error= EXIT_OUT_OF_MEMORY; @@ -7863,6 +8153,22 @@ mysql_getopt_value(const char *keyname, uint key_length, return (uchar**) &key_cache->param_partitions; } } + case OPT_REPLICATE_DO_DB: + case OPT_REPLICATE_DO_TABLE: + case OPT_REPLICATE_IGNORE_DB: + case OPT_REPLICATE_IGNORE_TABLE: + case OPT_REPLICATE_WILD_DO_TABLE: + case OPT_REPLICATE_WILD_IGNORE_TABLE: + case OPT_REPLICATE_REWRITE_DB: + { + /* Store current filter for mysqld_get_one_option() */ + if (!(cur_rpl_filter= get_or_create_rpl_filter(name, length))) + { + if (error) + *error= EXIT_OUT_OF_MEMORY; + } + return 0; + } } return option->value; } @@ -7903,7 +8209,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr) /* prepare all_options array */ my_init_dynamic_array(&all_options, sizeof(my_option), array_elements(my_long_options), - array_elements(my_long_options)/4); + array_elements(my_long_options)/4, MYF(0)); for (my_option *opt= my_long_options; opt < my_long_options + array_elements(my_long_options) - 1; opt++) @@ -7993,7 +8299,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr) global_system_variables.sql_mode= expand_sql_mode(global_system_variables.sql_mode); -#if defined(HAVE_BROKEN_REALPATH) +#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; my_disable_symlinks=1; have_symlink=SHOW_OPTION_NO; @@ -8098,8 +8404,30 @@ static int get_options(int *argc_ptr, char ***argv_ptr) if (!max_long_data_size_used) max_long_data_size= global_system_variables.max_allowed_packet; - /* Rember if max_user_connections was 0 at startup */ + /* Remember if max_user_connections was 0 at startup */ max_user_connections_checking= global_system_variables.max_user_connections != 0; + + { + sys_var *max_relay_log_size_var, *max_binlog_size_var; + /* If max_relay_log_size is 0, then set it to max_binlog_size */ + if (!global_system_variables.max_relay_log_size) + global_system_variables.max_relay_log_size= max_binlog_size; + + /* + Fix so that DEFAULT and limit checking works with max_relay_log_size + (Yes, this is a hack, but it's required as the definition of + max_relay_log_size allows it to be set to 0). + */ + max_relay_log_size_var= intern_find_sys_var("max_relay_log_size", 0); + max_binlog_size_var= intern_find_sys_var("max_binlog_size", 0); + if (max_binlog_size_var && max_relay_log_size_var) + { + max_relay_log_size_var->option.min_value= + max_binlog_size_var->option.min_value; + max_relay_log_size_var->option.def_value= + max_binlog_size_var->option.def_value; + } + } return 0; } @@ -8404,7 +8732,7 @@ void refresh_status(THD *thd) add_to_status(&global_status_var, &thd->status_var); /* Reset thread's status variables */ - bzero((uchar*) &thd->status_var, sizeof(thd->status_var)); + thd->set_status_var_init(); bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); thd->start_bytes_received= 0; @@ -8418,32 +8746,8 @@ void refresh_status(THD *thd) /* Set max_used_connections to the number of currently open - connections. Lock LOCK_thread_count out of LOCK_status to avoid - deadlocks. Status reset becomes not atomic, but status data is - not exact anyway. + connections. This is not perfect, but status data is not exact anyway. */ - mysql_mutex_lock(&LOCK_thread_count); max_used_connections= thread_count-delayed_insert_threads; - mysql_mutex_unlock(&LOCK_thread_count); } - -/***************************************************************************** - Instantiate variables for missing storage engines - This section should go away soon -*****************************************************************************/ - -/***************************************************************************** - Instantiate templates -*****************************************************************************/ - -#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION -/* Used templates */ -template class I_List<THD>; -template class I_List_iterator<THD>; -template class I_List<i_string>; -template class I_List<i_string_pair>; -template class I_List<Statement>; -template class I_List_iterator<Statement>; -#endif - |