diff options
Diffstat (limited to 'sql/mysqld.cc')
-rw-r--r-- | sql/mysqld.cc | 2893 |
1 files changed, 2124 insertions, 769 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a9359ba047e..0abb394f89f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, SkySQL Ab. + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" // Includes my_global.h #include "sql_priv.h" #include "unireg.h" #include <signal.h> @@ -40,9 +40,7 @@ #include "hostname.h" // hostname_cache_free, hostname_cache_init #include "sql_acl.h" // acl_free, grant_free, acl_init, // grant_init -#include "sql_base.h" // table_def_free, table_def_init, - // cached_open_tables, - // cached_table_definitions +#include "sql_base.h" #include "sql_test.h" // mysql_print_status #include "item_create.h" // item_create_cleanup, item_create_init #include "sql_servers.h" // servers_free, servers_init @@ -52,6 +50,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> @@ -85,6 +84,10 @@ ulong wsrep_running_threads = 0; // # of currently running wsrep threads #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE #include "../storage/perfschema/pfs_server.h" #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ +#include <mysql/psi/mysql_idle.h> +#include <mysql/psi/mysql_socket.h> +#include <mysql/psi/mysql_statement.h> +#include "mysql_com_server.h" #include "keycaches.h" #include "../storage/myisam/ha_myisam.h" @@ -118,7 +121,6 @@ ulong wsrep_running_threads = 0; // # of currently running wsrep threads #endif extern "C" { // Because of SCO 3.2V4.2 -#include <errno.h> #include <sys/stat.h> #ifndef __GNU_LIBRARY__ #define __GNU_LIBRARY__ // Skip warnings in getopt.h @@ -342,6 +344,13 @@ static PSI_rwlock_key key_rwlock_openssl; volatile sig_atomic_t ld_assume_kernel_is_set= 0; #endif +/** + Statement instrumentation key for replication. +*/ +#ifdef HAVE_PSI_STATEMENT_INTERFACE +PSI_statement_info stmt_info_rpl; +#endif + /* the default log output is log tables */ static bool lower_case_table_names_used= 0; static bool max_long_data_size_used= false; @@ -369,12 +378,14 @@ static I_List<THD> thread_cache; static bool binlog_format_used= false; LEX_STRING opt_init_connect, opt_init_slave; static mysql_cond_t COND_thread_cache, COND_flush_thread_cache; +mysql_cond_t COND_slave_init; static DYNAMIC_ARRAY all_options; /* Global variables */ #ifdef WITH_WSREP ulong my_bind_addr; +bool wsrep_new_cluster= false; #endif /* WITH_WSREP */ bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0; @@ -483,17 +494,21 @@ 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, service_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; +#ifdef RBR_TRIGGERS +ulong slave_run_triggers_for_rbr= 0; +#endif //RBR_TRIGGERS +ulong slave_ddl_exec_mode_options= SLAVE_EXEC_MODE_IDEMPOTENT; ulonglong slave_type_conversions_options; ulong thread_cache_size=0; ulonglong binlog_cache_size=0; @@ -502,11 +517,14 @@ ulong slave_max_allowed_packet= 0; ulonglong binlog_stmt_cache_size=0; ulonglong max_binlog_stmt_cache_size=0; ulonglong query_cache_size=0; -ulong refresh_version; /* Increments on each reload */ +ulong query_cache_limit=0; 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; @@ -516,6 +534,9 @@ 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 max_digest_length= 0; +ulong slave_retried_transactions; +ulong feature_files_opened_with_delayed_keys; ulonglong denied_connections; my_decimal decimal_zero; @@ -558,6 +579,13 @@ ulong rpl_recovery_rank=0; */ ulong stored_program_cache_size= 0; +ulong opt_slave_parallel_threads= 0; +ulong opt_slave_domain_parallel_threads= 0; +ulong opt_binlog_commit_wait_count= 0; +ulong opt_binlog_commit_wait_usec= 0; +ulong opt_slave_parallel_max_queued= 131072; +my_bool opt_gtid_ignore_duplicates= FALSE; + const double log_10[] = { 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, @@ -623,6 +651,19 @@ const char *in_left_expr_name= "<left expr>"; const char *in_additional_cond= "<IN COND>"; const char *in_having_cond= "<IN HAVING>"; +/** Number of connection errors when selecting on the listening port */ +ulong connection_errors_select= 0; +/** Number of connection errors when accepting sockets in the listening port. */ +ulong connection_errors_accept= 0; +/** Number of connection errors from TCP wrappers. */ +ulong connection_errors_tcpwrap= 0; +/** Number of connection errors from internal server errors. */ +ulong connection_errors_internal= 0; +/** Number of connection errors from the server max_connection limit. */ +ulong connection_errors_max_connection= 0; +/** Number of errors when reading the peer address. */ +ulong connection_errors_peer_addr= 0; + /* classes for comparation parsing/processing */ Eq_creator eq_creator; Ne_creator ne_creator; @@ -635,7 +676,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() @@ -672,19 +714,20 @@ 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_status, LOCK_show_status, LOCK_error_log, LOCK_short_uuid_generator, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_global_system_variables, LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, - LOCK_connection_count, LOCK_error_messages; + LOCK_connection_count, LOCK_error_messages, LOCK_slave_init; mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats, LOCK_global_table_stats, LOCK_global_index_stats; @@ -708,6 +751,8 @@ pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; +int mysqld_server_started=0, mysqld_server_initialized= 0; +File_parser_dummy_hook file_parser_dummy_hook; #ifdef WITH_WSREP mysql_mutex_t LOCK_wsrep_ready; mysql_cond_t COND_wsrep_ready; @@ -725,9 +770,6 @@ mysql_mutex_t LOCK_wsrep_desync; int wsrep_replaying= 0; static void wsrep_close_threads(THD* thd); #endif /* WITH_WSREP */ -int mysqld_server_started= 0; - -File_parser_dummy_hook file_parser_dummy_hook; /* replication parameters, if master_host is not NULL, we are a slave */ uint report_port= 0; @@ -766,32 +808,106 @@ static char **remaining_argv; int orig_argc; char **orig_argv; +static struct my_option pfs_early_options[]= +{ +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + {"performance_schema_instrument", OPT_PFS_INSTRUMENT, + "Default startup value for a performance schema instrument.", + &pfs_param.m_pfs_instrument, &pfs_param.m_pfs_instrument, 0, GET_STR, + OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_stages_current", 0, + "Default startup value for the events_stages_current consumer.", + &pfs_param.m_consumer_events_stages_current_enabled, + &pfs_param.m_consumer_events_stages_current_enabled, 0, GET_BOOL, + OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_stages_history", 0, + "Default startup value for the events_stages_history consumer.", + &pfs_param.m_consumer_events_stages_history_enabled, + &pfs_param.m_consumer_events_stages_history_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_stages_history_long", 0, + "Default startup value for the events_stages_history_long consumer.", + &pfs_param.m_consumer_events_stages_history_long_enabled, + &pfs_param.m_consumer_events_stages_history_long_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_statements_current", 0, + "Default startup value for the events_statements_current consumer.", + &pfs_param.m_consumer_events_statements_current_enabled, + &pfs_param.m_consumer_events_statements_current_enabled, 0, + GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_statements_history", 0, + "Default startup value for the events_statements_history consumer.", + &pfs_param.m_consumer_events_statements_history_enabled, + &pfs_param.m_consumer_events_statements_history_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_statements_history_long", 0, + "Default startup value for the events_statements_history_long consumer.", + &pfs_param.m_consumer_events_statements_history_long_enabled, + &pfs_param.m_consumer_events_statements_history_long_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_waits_current", 0, + "Default startup value for the events_waits_current consumer.", + &pfs_param.m_consumer_events_waits_current_enabled, + &pfs_param.m_consumer_events_waits_current_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_waits_history", 0, + "Default startup value for the events_waits_history consumer.", + &pfs_param.m_consumer_events_waits_history_enabled, + &pfs_param.m_consumer_events_waits_history_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_events_waits_history_long", 0, + "Default startup value for the events_waits_history_long consumer.", + &pfs_param.m_consumer_events_waits_history_long_enabled, + &pfs_param.m_consumer_events_waits_history_long_enabled, 0, + GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_global_instrumentation", 0, + "Default startup value for the global_instrumentation consumer.", + &pfs_param.m_consumer_global_instrumentation_enabled, + &pfs_param.m_consumer_global_instrumentation_enabled, 0, + GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_thread_instrumentation", 0, + "Default startup value for the thread_instrumentation consumer.", + &pfs_param.m_consumer_thread_instrumentation_enabled, + &pfs_param.m_consumer_thread_instrumentation_enabled, 0, + GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0}, + {"performance_schema_consumer_statements_digest", 0, + "Default startup value for the statements_digest consumer.", + &pfs_param.m_consumer_statement_digest_enabled, + &pfs_param.m_consumer_statement_digest_enabled, 0, + GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0} +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ +}; + #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, key_LOCK_gdl, key_LOCK_global_system_variables, key_LOCK_manager, key_LOCK_prepared_stmt_count, - key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, - key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data, + key_LOCK_rpl_status, key_LOCK_server_started, + key_LOCK_status, key_LOCK_show_status, + key_LOCK_system_variables_hash, key_LOCK_thd_data, key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log, key_master_info_data_lock, key_master_info_run_lock, key_master_info_sleep_lock, key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, + key_rpl_group_info_sleep_lock, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, - key_relay_log_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; #ifdef WITH_WSREP PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, @@ -800,13 +916,18 @@ PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync; #endif 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; +PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered, + key_LOCK_slave_init; +PSI_mutex_key key_TABLE_SHARE_LOCK_share; static PSI_mutex_info all_server_mutexes[]= { @@ -815,6 +936,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 @@ -822,7 +944,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}, @@ -840,13 +963,15 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL}, { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL}, { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL}, + { &key_LOCK_show_status, "LOCK_show_status", PSI_FLAG_GLOBAL}, { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL}, - { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL}, { &key_LOCK_stats, "LOCK_stats", PSI_FLAG_GLOBAL}, { &key_LOCK_global_user_client_stats, "LOCK_global_user_client_stats", PSI_FLAG_GLOBAL}, { &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}, @@ -858,14 +983,15 @@ 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_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0}, { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL}, { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL}, { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, + { &key_LOCK_slave_init, "LOCK_slave_init", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, - { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, #ifdef WITH_WSREP { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, @@ -878,7 +1004,14 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL}, #endif - { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} + { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, + { &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, @@ -902,7 +1035,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, @@ -911,7 +1046,7 @@ 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; @@ -920,9 +1055,15 @@ PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread; #endif /* WITH_WSREP */ -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_queue, key_COND_rpl_thread, + key_COND_rpl_thread_stop, key_COND_rpl_thread_pool, + key_COND_parallel_entry, key_COND_group_commit_orderer, + key_COND_prepare_ordered, key_COND_slave_init; +PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates; static PSI_cond_info all_server_conds[]= { @@ -935,15 +1076,17 @@ 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}, { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL}, { &key_delayed_insert_cond, "Delayed_insert::cond", 0}, { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0}, @@ -956,7 +1099,7 @@ 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}, @@ -969,12 +1112,23 @@ static PSI_cond_info all_server_conds[]= { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL}, #endif - { &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_queue, "COND_rpl_thread_queue", 0}, + { &key_COND_rpl_thread_stop, "COND_rpl_thread_stop", 0}, + { &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0}, + { &key_COND_parallel_entry, "COND_parallel_entry", 0}, + { &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0}, + { &key_COND_prepare_ordered, "COND_prepare_ordered", 0}, + { &key_COND_slave_init, "COND_slave_init", 0}, + { &key_COND_wait_gtid, "COND_wait_gtid", 0}, + { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 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[]= { @@ -999,9 +1153,15 @@ 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} }; +#ifdef HAVE_MMAP +PSI_file_key key_file_map; +#endif /* HAVE_MMAP */ + PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest, key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file, key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load, @@ -1011,75 +1171,84 @@ 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[]= -{ - { &key_file_binlog, "binlog", 0}, - { &key_file_binlog_index, "binlog_index", 0}, - { &key_file_relaylog, "relaylog", 0}, - { &key_file_relaylog_index, "relaylog_index", 0}, - { &key_file_casetest, "casetest", 0}, - { &key_file_dbopt, "dbopt", 0}, - { &key_file_des_key_file, "des_key_file", 0}, - { &key_file_ERRMSG, "ERRMSG", 0}, - { &key_select_to_file, "select_to_file", 0}, - { &key_file_fileparser, "file_parser", 0}, - { &key_file_frm, "FRM", 0}, - { &key_file_global_ddl_log, "global_ddl_log", 0}, - { &key_file_load, "load", 0}, - { &key_file_loadfile, "LOAD_FILE", 0}, - { &key_file_log_event_data, "log_event_data", 0}, - { &key_file_log_event_info, "log_event_info", 0}, - { &key_file_master_info, "master_info", 0}, - { &key_file_misc, "misc", 0}, - { &key_file_partition, "partition", 0}, - { &key_file_pid, "pid", 0}, - { &key_file_query_log, "query_log", 0}, - { &key_file_relay_log_info, "relay_log_info", 0}, - { &key_file_send_file, "send_file", 0}, - { &key_file_slow_log, "slow_log", 0}, - { &key_file_tclog, "tclog", 0}, - { &key_file_trg, "trigger_name", 0}, - { &key_file_trn, "trigger", 0}, - { &key_file_init, "init", 0} -}; +#endif /* HAVE_PSI_INTERFACE */ -/** - Initialise all the performance schema instrumentation points - used by the server. -*/ -void init_server_psi_keys(void) +#ifdef HAVE_PSI_STATEMENT_INTERFACE +PSI_statement_info stmt_info_new_packet; +#endif + +#ifndef EMBEDDED_LIBRARY +void net_before_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */) { - const char* category= "sql"; - int count; + THD *thd; + thd= static_cast<THD*> (user_data); + DBUG_ASSERT(thd != NULL); - if (PSI_server == NULL) - return; + /* + We only come where when the server is IDLE, waiting for the next command. + Technically, it is a wait on a socket, which may take a long time, + because the call is blocking. + Disable the socket instrumentation, to avoid recording a SOCKET event. + Instead, start explicitly an IDLE event. + */ + MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE); + MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state); +} - count= array_elements(all_server_mutexes); - PSI_server->register_mutex(category, all_server_mutexes, count); +void net_after_header_psi(struct st_net *net, void *user_data, + size_t /* unused: count */, my_bool rc) +{ + THD *thd; + thd= static_cast<THD*> (user_data); + DBUG_ASSERT(thd != NULL); - count= array_elements(all_server_rwlocks); - PSI_server->register_rwlock(category, all_server_rwlocks, count); + /* + The server just got data for a network packet header, + from the network layer. + The IDLE event is now complete, since we now have a message to process. + We need to: + - start a new STATEMENT event + - start a new STAGE event, within this statement, + - start recording SOCKET WAITS events, within this stage. + The proper order is critical to get events numbered correctly, + and nested in the proper parent. + */ + MYSQL_END_IDLE_WAIT(thd->m_idle_psi); - count= array_elements(all_server_conds); - PSI_server->register_cond(category, all_server_conds, count); + if (! rc) + { + thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, + stmt_info_new_packet.m_key, + thd->db, thd->db_length, + thd->charset()); - count= array_elements(all_server_threads); - PSI_server->register_thread(category, all_server_threads, count); + THD_STAGE_INFO(thd, stage_init); + } - count= array_elements(all_server_files); - PSI_server->register_file(category, all_server_files, count); + /* + TODO: consider recording a SOCKET event for the bytes just read, + by also passing count here. + */ + MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE); } -#endif /* HAVE_PSI_INTERFACE */ -/* - Since buffered_option_error_reporter is only used currently - for parsing performance schema options, this code is not needed - when the performance schema is not compiled in. -*/ -#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +void init_net_server_extension(THD *thd) +{ + /* Start with a clean state for connection events. */ + thd->m_idle_psi= NULL; + thd->m_statement_psi= NULL; + /* Hook up the NET_SERVER callback in the net layer. */ + thd->m_net_server_extension.m_user_data= thd; + thd->m_net_server_extension.m_before_header= net_before_header_psi; + thd->m_net_server_extension.m_after_header= net_after_header_psi; + /* Activate this private extension for the mysqld server. */ + thd->net.extension= & thd->m_net_server_extension; +} +#endif /* EMBEDDED_LIBRARY */ + /** A log message for the error log, buffered in memory. Log messages are temporarily buffered when generated before the error log @@ -1176,7 +1345,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() @@ -1215,6 +1384,9 @@ void Buffered_logs::print() /** Logs reported before a logger is available. */ static Buffered_logs buffered_logs; +static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock; +struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD() + #ifndef EMBEDDED_LIBRARY /** Error reporter that buffer log messages. @@ -1233,14 +1405,34 @@ static void buffered_option_error_reporter(enum loglevel level, va_end(args); buffered_logs.buffer(level, buffer); } -C_MODE_END -#endif /* !EMBEDDED_LIBRARY */ -#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ -static my_socket unix_sock, base_ip_sock, extra_ip_sock; -struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD() -#ifndef EMBEDDED_LIBRARY +/** + Character set and collation error reporter that prints to sql error log. + @param level log message level + @param format log message format string + + This routine is used to print character set and collation + warnings and errors inside an already running mysqld server, + e.g. when a character set or collation is requested for the very first time + and its initialization does not go well for some reasons. + + Note: At early mysqld initialization stage, + when error log is not yet available, + we use buffered_option_error_reporter() instead, + to print general character set subsystem initialization errors, + such as Index.xml syntax problems, bad XML tag hierarchy, etc. +*/ +static void charset_error_reporter(enum loglevel level, + const char *format, ...) +{ + va_list args; + va_start(args, format); + vprint_msg_to_log(level, format, args); + va_end(args); +} +C_MODE_END + struct passwd *user_info; static pthread_t select_thread; #endif @@ -1278,7 +1470,9 @@ bool mysqld_embedded=0; bool mysqld_embedded=1; #endif +#ifndef EMBEDDED_LIBRARY static my_bool plugins_are_initialized= FALSE; +#endif #ifndef DBUG_OFF static const char* default_dbug_option; @@ -1301,7 +1495,9 @@ HANDLE smem_event_connect_request= 0; my_bool opt_use_ssl = 0; char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, - *opt_ssl_cipher= NULL, *opt_ssl_key= NULL; + *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL, + *opt_ssl_crlpath= NULL; + static scheduler_functions thread_scheduler_struct, extra_thread_scheduler_struct; scheduler_functions *thread_scheduler= &thread_scheduler_struct, @@ -1333,12 +1529,16 @@ 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); static int mysql_init_variables(void); static int get_options(int *argc_ptr, char ***argv_ptr); static bool add_terminator(DYNAMIC_ARRAY *options); +static bool add_many_options(DYNAMIC_ARRAY *, my_option *, size_t); extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static int init_thread_environment(); static char *get_relative_path(const char *path); @@ -1429,17 +1629,17 @@ static void close_connections(void) DBUG_PRINT("quit",("Closing sockets")); if (!opt_disable_networking ) { - if (base_ip_sock != INVALID_SOCKET) + if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET) { (void) mysql_socket_shutdown(base_ip_sock, SHUT_RDWR); - (void) closesocket(base_ip_sock); - base_ip_sock= INVALID_SOCKET; + (void) mysql_socket_close(base_ip_sock); + base_ip_sock= MYSQL_INVALID_SOCKET; } - if (extra_ip_sock != INVALID_SOCKET) + if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET) { (void) mysql_socket_shutdown(extra_ip_sock, SHUT_RDWR); - (void) closesocket(extra_ip_sock); - extra_ip_sock= INVALID_SOCKET; + (void) mysql_socket_close(extra_ip_sock); + extra_ip_sock= MYSQL_INVALID_SOCKET; } } #ifdef _WIN32 @@ -1467,12 +1667,12 @@ static void close_connections(void) } #endif #ifdef HAVE_SYS_UN_H - if (unix_sock != INVALID_SOCKET) + if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET) { (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR); - (void) closesocket(unix_sock); + (void) mysql_socket_close(unix_sock); (void) unlink(mysqld_unix_port); - unix_sock= INVALID_SOCKET; + unix_sock= MYSQL_INVALID_SOCKET; } #endif end_thr_alarm(0); // Abort old alarms. @@ -1532,8 +1732,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); /* @@ -1596,7 +1809,7 @@ static void close_connections(void) /* All threads has now been aborted */ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); mysql_mutex_lock(&LOCK_thread_count); - while (thread_count) + while (thread_count || service_thread_count) { mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); @@ -1609,22 +1822,14 @@ static void close_connections(void) #ifdef HAVE_CLOSE_SERVER_SOCK -static void close_socket(my_socket sock, const char *info) +static void close_socket(MYSQL_SOCKET sock, const char *info) { DBUG_ENTER("close_socket"); - if (sock != INVALID_SOCKET) + if (mysql_socket_getfd(sock) != INVALID_SOCKET) { DBUG_PRINT("info", ("calling shutdown on %s socket", info)); (void) mysql_socket_shutdown(sock, SHUT_RDWR); -#if defined(__NETWARE__) - /* - The following code is disabled for normal systems as it causes MySQL - to hang on AIX 4.3 during shutdown - */ - DBUG_PRINT("info", ("calling closesocket on %s socket", info)); - (void) closesocket(tmp_sock); -#endif } DBUG_VOID_RETURN; } @@ -1640,9 +1845,9 @@ static void close_server_sock() close_socket(extra_ip_sock, "TCP/IP"); close_socket(unix_sock, "unix/IP"); - if (unix_sock != INVALID_SOCKET) + if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET) (void) unlink(mysqld_unix_port); - base_ip_sock= extra_ip_sock= unix_sock= INVALID_SOCKET; + base_ip_sock= extra_ip_sock= unix_sock= MYSQL_INVALID_SOCKET; DBUG_VOID_RETURN; #endif @@ -1874,7 +2079,6 @@ extern "C" void unireg_abort(int exit_code) wsrep_deinit(true); } #endif // WITH_WSREP - clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); mysqld_exit(exit_code); @@ -1882,11 +2086,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(); @@ -1895,6 +2102,7 @@ static void mysqld_exit(int exit_code) #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE shutdown_performance_schema(); // we do it as late as possible #endif + DBUG_LEAVE; exit(exit_code); /* purecov: inspected */ } @@ -1906,7 +2114,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) + my_bitmap_free(&slave_error_mask); +#endif stop_handle_manager(); release_ddl_log(); @@ -1921,24 +2134,20 @@ 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(); - table_def_start_shutdown(); + tdc_start_shutdown(); plugin_shutdown(); udf_free(); ha_end(); @@ -1946,7 +2155,7 @@ void clean_up(bool print_message) tc_log->close(); delegates_destroy(); xid_cache_free(); - table_def_free(); + tdc_deinit(); mdl_destroy(); key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache); wt_end(); @@ -1958,24 +2167,24 @@ void clean_up(bool print_message) if (defaults_argv) free_defaults(defaults_argv); free_tmpdir(&mysql_tmpdir_list); - bitmap_free(&temp_pool); + my_bitmap_free(&temp_pool); free_max_user_conn(); free_global_user_stats(); free_global_client_stats(); free_global_table_stats(); free_global_index_stats(); delete_dynamic(&all_options); + free_all_rpl_filters(); #ifdef HAVE_REPLICATION end_slave_list(); #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(); @@ -1996,6 +2205,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")); @@ -2004,6 +2216,14 @@ void clean_up(bool print_message) mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); + free_list(opt_plugin_load_list_ptr); + + if (THR_THD) + (void) pthread_key_delete(THR_THD); + + if (THR_MALLOC) + (void) pthread_key_delete(THR_MALLOC); + /* The following lines may never be executed as the main thread may have killed us @@ -2039,7 +2259,9 @@ 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_show_status); mysql_mutex_destroy(&LOCK_delayed_insert); mysql_mutex_destroy(&LOCK_delayed_status); mysql_mutex_destroy(&LOCK_delayed_create); @@ -2060,7 +2282,6 @@ static void clean_up_mutexes() #endif /* HAVE_OPENSSL */ #ifdef HAVE_REPLICATION mysql_mutex_destroy(&LOCK_rpl_status); - mysql_cond_destroy(&COND_rpl_status); #endif /* HAVE_REPLICATION */ mysql_mutex_destroy(&LOCK_active_mi); mysql_rwlock_destroy(&LOCK_sys_init_connect); @@ -2090,7 +2311,10 @@ 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); + mysql_mutex_destroy(&LOCK_slave_init); + mysql_cond_destroy(&COND_slave_init); DBUG_VOID_RETURN; } @@ -2276,14 +2500,15 @@ static void set_root(const char *path) Activate usage of a tcp port */ -static my_socket activate_tcp_port(uint port) +static MYSQL_SOCKET activate_tcp_port(uint port) { struct addrinfo *ai, *a; struct addrinfo hints; int error; int arg; char port_buf[NI_MAXSERV]; - my_socket ip_sock= INVALID_SOCKET; + const char *real_bind_addr_str; + MYSQL_SOCKET ip_sock= MYSQL_INVALID_SOCKET; DBUG_ENTER("activate_tcp_port"); DBUG_PRINT("general",("IP Socket is %d",port)); @@ -2291,34 +2516,55 @@ static my_socket activate_tcp_port(uint port) hints.ai_flags= AI_PASSIVE; hints.ai_socktype= SOCK_STREAM; hints.ai_family= AF_UNSPEC; + + if (my_bind_addr_str && strcmp(my_bind_addr_str, "*") == 0) + real_bind_addr_str= NULL; // windows doesn't seem to support * here + else + real_bind_addr_str= my_bind_addr_str; my_snprintf(port_buf, NI_MAXSERV, "%d", port); - error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai); + error= getaddrinfo(real_bind_addr_str, port_buf, &hints, &ai); if (error != 0) { DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error)); - sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ + + sql_print_error("%s: %s", ER_DEFAULT(ER_IPSOCK_ERROR), gai_strerror(error)); unireg_abort(1); /* purecov: tested */ } + /* + special case: for wildcard addresses prefer ipv6 over ipv4, + because we later switch off IPV6_V6ONLY, so ipv6 wildcard + addresses will work for ipv4 too + */ + if (!real_bind_addr_str && ai->ai_family == AF_INET && ai->ai_next + && ai->ai_next->ai_family == AF_INET6) + { + a= ai; + ai= ai->ai_next; + a->ai_next= ai->ai_next; + ai->ai_next= a; + } + for (a= ai; a != NULL; a= a->ai_next) { - ip_sock= socket(a->ai_family, a->ai_socktype, a->ai_protocol); - - char ip_addr[INET6_ADDRSTRLEN]; + ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family, + a->ai_socktype, a->ai_protocol); + char ip_addr[INET6_ADDRSTRLEN]; if (vio_get_normalized_ip_string(a->ai_addr, a->ai_addrlen, ip_addr, sizeof (ip_addr))) { ip_addr[0]= 0; } - if (ip_sock == INVALID_SOCKET) + if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET) { - sql_print_error("Failed to create a socket for %s '%s': errno: %d.", - (a->ai_family == AF_INET) ? "IPv4" : "IPv6", - (const char *) ip_addr, - (int) socket_errno); + sql_print_message_func func= real_bind_addr_str ? sql_print_error + : sql_print_warning; + func("Failed to create a socket for %s '%s': errno: %d.", + (a->ai_family == AF_INET) ? "IPv4" : "IPv6", + (const char *) ip_addr, (int) socket_errno); } else { @@ -2328,20 +2574,23 @@ static my_socket activate_tcp_port(uint port) } } - if (ip_sock == INVALID_SOCKET) + if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET) { DBUG_PRINT("error",("Got error: %d from socket()",socket_errno)); sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ unireg_abort(1); /* purecov: tested */ } + mysql_socket_set_thread_owner(ip_sock); + #ifndef __WIN__ /* We should not use SO_REUSEADDR on windows as this would enable a user to open two mysqld servers with the same TCP/IP port. */ arg= 1; - (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); + (void) mysql_socket_setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg, + sizeof(arg)); #endif /* __WIN__ */ #ifdef IPV6_V6ONLY @@ -2357,8 +2606,8 @@ static my_socket activate_tcp_port(uint port) if (a->ai_family == AF_INET6) { arg= 0; - (void) setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, - sizeof(arg)); + (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, + (char*)&arg, sizeof(arg)); } #endif /* @@ -2373,7 +2622,7 @@ static my_socket activate_tcp_port(uint port) uint waited, retry, this_wait; for (waited= 0, retry= 1; ; retry++, waited+= this_wait) { - if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) || + if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) || (socket_errno != SOCKET_EADDRINUSE) || (waited >= mysqld_port_timeout)) break; @@ -2392,7 +2641,7 @@ static my_socket activate_tcp_port(uint port) "port: %u ?", port); unireg_abort(1); } - if (listen(ip_sock,(int) back_log) < 0) + if (mysql_socket_listen(ip_sock,(int) back_log) < 0) { sql_perror("Can't start server: listen() on TCP/IP port"); sql_print_error("listen() on TCP/IP failed with error %d", @@ -2400,8 +2649,9 @@ static my_socket activate_tcp_port(uint port) unireg_abort(1); } #if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) - (void) fcntl(ip_sock, F_SETFD, FD_CLOEXEC); + (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ + DBUG_RETURN(ip_sock); } @@ -2496,21 +2746,26 @@ static void network_init(void) (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } - if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + unix_sock= mysql_socket_socket(key_socket_unix, AF_UNIX, SOCK_STREAM, 0); + if (mysql_socket_getfd(unix_sock) < 0) { sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */ unireg_abort(1); /* purecov: inspected */ } + + mysql_socket_set_thread_owner(unix_sock); + bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, mysqld_unix_port); (void) unlink(mysqld_unix_port); arg= 1; - (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg, - sizeof(arg)); + (void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR, + (char*)&arg, sizeof(arg)); umask(0); - if (bind(unix_sock, reinterpret_cast<struct sockaddr *>(&UNIXaddr), - sizeof(UNIXaddr)) < 0) + if (mysql_socket_bind(unix_sock, + reinterpret_cast<struct sockaddr *>(&UNIXaddr), + sizeof(UNIXaddr)) < 0) { sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */ sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port); @@ -2520,11 +2775,11 @@ static void network_init(void) #if defined(S_IFSOCK) && defined(SECURE_SOCKETS) (void) chmod(mysqld_unix_port,S_IFSOCK); /* Fix solaris 2.6 bug */ #endif - if (listen(unix_sock,(int) back_log) < 0) + if (mysql_socket_listen(unix_sock,(int) back_log) < 0) sql_print_warning("listen() on Unix socket failed with error %d", socket_errno); -#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) - (void) fcntl(unix_sock, F_SETFD, FD_CLOEXEC); +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) + (void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ } #endif @@ -2560,7 +2815,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 */ @@ -2617,6 +2872,47 @@ 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); + signal_thd_deleted(); +} + + +/* + Send a signal to unblock close_conneciton() if there is no more + threads running with a THD attached + + It's safe to check for thread_count and service_thread_count outside + of a mutex as we are only interested to see if they where decremented + to 0 by a previous unlink_thd() call. + + We should only signal COND_thread_count if both variables are 0, + false positives are ok. +*/ + +void signal_thd_deleted() +{ + if (!thread_count && ! service_thread_count) + { + /* Signal close_connections() that all THD's are freed */ + 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 @@ -2645,19 +2941,11 @@ void unlink_thd(THD *thd) sync feature has been shut down at this point. */ DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5);); - if (unlikely(abort_loop)) - { - /* - During shutdown, we have to delete thd inside the mutex - to not refer to mutexes that may be deleted during shutdown - */ - delete thd; - thd= 0; - } - thread_count--; mysql_mutex_unlock(&LOCK_thread_count); delete thd; + thread_safe_decrement32(&thread_count, &thread_count_lock); + DBUG_VOID_RETURN; } @@ -2669,7 +2957,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 @@ -2680,7 +2968,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) { @@ -2688,17 +2978,16 @@ static bool cache_thread() DBUG_PRINT("info", ("Adding thread to cache")); cached_thread_count++; -#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_PSI_THREAD_INTERFACE /* Delete the instrumentation for the job that just completed, before parking this pthread in the cache (blocked on COND_thread_cache). */ - if (likely(PSI_server != NULL)) - PSI_server->delete_current_thread(); + PSI_THREAD_CALL(delete_current_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); @@ -2707,21 +2996,19 @@ 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(); -#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_PSI_THREAD_INTERFACE /* Create new instrumentation for the new THD job, and attach it to this running pthread. */ - if (likely(PSI_server != NULL)) - { - PSI_thread *psi= PSI_server->new_thread(key_thread_one_connection, - thd, thd->thread_id); - if (likely(psi != NULL)) - PSI_server->set_thread(psi); - } + PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_one_connection, + thd, thd->thread_id); + PSI_THREAD_CALL(set_thread)(psi); #endif /* @@ -2732,11 +3019,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); } @@ -2764,33 +3056,25 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_ENTER("one_thread_per_connection_end"); #ifdef WITH_WSREP const bool wsrep_applier(thd->wsrep_applier); -#endif /* WITH_WSREP */ +#endif unlink_thd(thd); /* Mark that current_thd is not valid anymore */ - my_pthread_setspecific_ptr(THR_THD, 0); + set_current_thd(0); #ifdef WITH_WSREP - if (put_in_cache && !wsrep_applier) + if (!wsrep_applier && put_in_cache && cache_thread()) #else - if (put_in_cache) + if (put_in_cache && cache_thread()) #endif /* WITH_WSREP */ - { - mysql_mutex_lock(&LOCK_thread_count); - put_in_cache= cache_thread(); - mysql_mutex_unlock(&LOCK_thread_count); - if (put_in_cache) - DBUG_RETURN(0); // Thread is reused - } + 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")); + signal_thd_deleted(); 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 @@ -2799,15 +3083,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; } @@ -3214,8 +3500,8 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) should not be any other mysql_cond_signal() calls. */ mysql_mutex_lock(&LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); (void) pthread_sigmask(SIG_BLOCK,&set,NULL); for (;;) @@ -3251,10 +3537,9 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) if (!abort_loop) { abort_loop=1; // mark abort for threads -#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_PSI_THREAD_INTERFACE /* Delete the instrumentation for the signal thread */ - if (likely(PSI_server != NULL)) - PSI_server->delete_current_thread(); + PSI_THREAD_CALL(delete_current_thread)(); #endif #ifdef USE_ONE_SIGNAL_HAND pthread_t tmp; @@ -3326,28 +3611,28 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); void my_message_sql(uint error, const char *str, myf MyFlags) { THD *thd= current_thd; - MYSQL_ERROR::enum_warning_level level; + Sql_condition::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); if (MyFlags & ME_JUST_INFO) { - level= MYSQL_ERROR::WARN_LEVEL_NOTE; + level= Sql_condition::WARN_LEVEL_NOTE; func= sql_print_information; } else if (MyFlags & ME_JUST_WARNING) { - level= MYSQL_ERROR::WARN_LEVEL_WARN; + level= Sql_condition::WARN_LEVEL_WARN; func= sql_print_warning; } else { - level= MYSQL_ERROR::WARN_LEVEL_ERROR; + level= Sql_condition::WARN_LEVEL_ERROR; func= sql_print_error; } @@ -3369,9 +3654,9 @@ 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); +extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size); void *my_str_malloc_mysqld(size_t size) { @@ -3383,7 +3668,11 @@ void my_str_free_mysqld(void *ptr) { my_free(ptr); } -#endif /* EMBEDDED_LIBRARY */ + +void *my_str_realloc_mysqld(void *ptr, size_t size) +{ + return my_realloc(ptr, size, MYF(MY_FAE)); +} #ifdef __WIN__ @@ -3415,24 +3704,57 @@ 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; + my_str_realloc= &my_str_realloc_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 +} /** @@ -3490,6 +3812,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}, @@ -3505,6 +3828,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}, @@ -3513,7 +3837,9 @@ SHOW_VAR com_status_vars[]= { {"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS}, {"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}, + {"get_diagnostics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), 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}, @@ -3539,6 +3865,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}, @@ -3563,6 +3890,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}, @@ -3594,9 +3922,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}, @@ -3604,6 +3933,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}, @@ -3618,21 +3949,154 @@ SHOW_VAR com_status_vars[]= { {NullS, NullS, SHOW_LONG} }; + +#ifdef HAVE_PSI_STATEMENT_INTERFACE +PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1]; +PSI_statement_info com_statement_info[(uint) COM_END + 1]; + +/** + Initialize the command names array. + Since we do not want to maintain a separate array, + this is populated from data mined in com_status_vars, + which already has one name for each command. +*/ +void init_sql_statement_info() +{ + char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]); + char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]); + int record_size= (char*) offsetof(STATUS_VAR, com_stat[1]) + - (char*) offsetof(STATUS_VAR, com_stat[0]); + char *ptr; + uint i; + uint com_index; + + static const char* dummy= ""; + for (i= 0; i < ((uint) SQLCOM_END + 1); i++) + { + sql_statement_info[i].m_name= dummy; + sql_statement_info[i].m_flags= 0; + } + + SHOW_VAR *var= &com_status_vars[0]; + while (var->name != NULL) + { + ptr= var->value; + if ((first_com <= ptr) && (ptr <= last_com)) + { + com_index= ((int)(ptr - first_com))/record_size; + DBUG_ASSERT(com_index < (uint) SQLCOM_END); + sql_statement_info[com_index].m_name= var->name; + } + var++; + } + + DBUG_ASSERT(strcmp(sql_statement_info[(uint) SQLCOM_SELECT].m_name, "select") == 0); + DBUG_ASSERT(strcmp(sql_statement_info[(uint) SQLCOM_SIGNAL].m_name, "signal") == 0); + + sql_statement_info[(uint) SQLCOM_END].m_name= "error"; +} + +void init_com_statement_info() +{ + uint index; + + for (index= 0; index < (uint) COM_END + 1; index++) + { + com_statement_info[index].m_name= command_name[index].str; + com_statement_info[index].m_flags= 0; + } + + /* "statement/abstract/query" can mutate into "statement/sql/..." */ + com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE; +} +#endif + + +#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); +} +} + + static int init_common_variables() { umask(((~my_umask) & 0666)); + connection_errors_select= 0; + connection_errors_accept= 0; + connection_errors_tcpwrap= 0; + connection_errors_internal= 0; + connection_errors_max_connection= 0; + connection_errors_peer_addr= 0; 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; @@ -3674,8 +4138,9 @@ static int init_common_variables() #ifdef HAVE_PSI_INTERFACE /* Complete the mysql_bin_log initialization. - Instrumentation keys are known only after the performance schema initialization, - and can not be set in the MYSQL_BIN_LOG constructor (called before main()). + Instrumentation keys are known only after the performance schema + initialization, and can not be set in the MYSQL_BIN_LOG + constructor (called before main()). */ mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index, key_BINLOG_update_cond, @@ -3866,7 +4331,7 @@ static int init_common_variables() /* MyISAM requires two file handles per table. */ wanted_files= (10 + max_connections + extra_max_connections + - table_cache_size*2); + tc_size * 2); /* We are trying to allocate no less than max_connections*5 file handles (i.e. we are trying to set the limit so that they will @@ -3877,7 +4342,7 @@ static int init_common_variables() can't get max_connections*5 but still got no less than was requested (value of wanted_files). */ - max_open_files= max(max(wanted_files, + max_open_files= MY_MAX(MY_MAX(wanted_files, (max_connections + extra_max_connections)*5), open_files_limit); files= my_set_max_open_files(max_open_files); @@ -3890,23 +4355,22 @@ static int init_common_variables() If we have requested too much file handles than we bring max_connections in supported bounds. */ - max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2, + max_connections= (ulong) MY_MIN(files-10-TABLE_OPEN_CACHE_MIN*2, max_connections); /* - Decrease table_cache_size according to max_connections, but - not below TABLE_OPEN_CACHE_MIN. Outer min() ensures that we - never increase table_cache_size automatically (that could + Decrease tc_size according to max_connections, but + not below TABLE_OPEN_CACHE_MIN. Outer MY_MIN() ensures that we + never increase tc_size automatically (that could happen if max_connections is decreased above). */ - table_cache_size= (ulong) min(max((files-10-max_connections)/2, - TABLE_OPEN_CACHE_MIN), - table_cache_size); + tc_size= (ulong) MY_MIN(MY_MAX((files - 10 - max_connections) / 2, + TABLE_OPEN_CACHE_MIN), tc_size); DBUG_PRINT("warning", ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", - files, max_connections, table_cache_size)); + files, max_connections, tc_size)); if (global_system_variables.log_warnings) sql_print_warning("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", - files, max_connections, table_cache_size); + files, max_connections, tc_size); } else if (global_system_variables.log_warnings) sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files); @@ -3929,12 +4393,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 @@ -3968,6 +4427,10 @@ static int init_common_variables() default_collation= get_charset_by_name(default_collation_name, MYF(0)); if (!default_collation) { +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + buffered_logs.print(); + buffered_logs.cleanup(); +#endif sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name); return 1; } @@ -3985,7 +4448,15 @@ static int init_common_variables() global_system_variables.collation_database= default_charset_info; global_system_variables.collation_connection= default_charset_info; global_system_variables.character_set_results= default_charset_info; - global_system_variables.character_set_client= default_charset_info; + if (default_charset_info->mbminlen > 1) + { + global_system_variables.character_set_client= &my_charset_latin1; + sql_print_warning("Cannot use %s as character_set_client, %s will be used instead", + default_charset_info->csname, + global_system_variables.character_set_client->csname); + } + else + global_system_variables.character_set_client= default_charset_info; if (!(character_set_filesystem= get_charset_by_csname(character_set_filesystem_name, @@ -4026,7 +4497,7 @@ static int init_common_variables() #endif /* defined(ENABLED_DEBUG_SYNC) */ #if (ENABLE_TEMP_POOL) - if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) + if (use_temp_pool && my_bitmap_init(&temp_pool,0,1024,1)) return 1; #else use_temp_pool= 0; @@ -4104,8 +4575,11 @@ static int init_common_variables() 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_show_status, &LOCK_show_status, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_LOCK_delayed_insert, &LOCK_delayed_insert, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_delayed_status, @@ -4117,6 +4591,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, @@ -4136,8 +4611,12 @@ 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); + mysql_mutex_init(key_LOCK_slave_init, &LOCK_slave_init, + MY_MUTEX_INIT_SLOW); + mysql_cond_init(key_COND_slave_init, &COND_slave_init, NULL); #ifdef HAVE_OPENSSL mysql_mutex_init(key_LOCK_des_key_file, @@ -4161,7 +4640,6 @@ static int init_thread_environment() mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL); #ifdef HAVE_REPLICATION mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_rpl_status, &COND_rpl_status, NULL); #endif mysql_mutex_init(key_LOCK_server_started, &LOCK_server_started, MY_MUTEX_INIT_FAST); @@ -4170,18 +4648,18 @@ 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; - } +#ifdef HAVE_REPLICATION + rpl_init_gtid_slave_state(); + rpl_init_gtid_waiting(); +#endif + #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_ready, &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); @@ -4203,7 +4681,8 @@ static int init_thread_environment() mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST); #endif - return 0; + + DBUG_RETURN(0); } @@ -4280,9 +4759,9 @@ static void init_ssl() /* having ssl_acceptor_fd != 0 signals the use of SSL */ ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, - opt_ssl_cipher, &error); + opt_ssl_cipher, &error, + opt_ssl_crl, opt_ssl_crlpath); DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd)); - ERR_remove_state(0); if (!ssl_acceptor_fd) { sql_print_warning("Failed to setup SSL"); @@ -4290,6 +4769,14 @@ static void init_ssl() opt_use_ssl = 0; have_ssl= SHOW_OPTION_DISABLED; } + if (global_system_variables.log_warnings > 0) + { + ulong err; + while ((err= ERR_get_error())) + sql_print_warning("SSL error: %s", ERR_error_string(err, NULL)); + } + else + ERR_remove_state(0); } else { @@ -4349,12 +4836,13 @@ static int init_server_components() all things are initialized so that unireg_abort() doesn't fail */ mdl_init(); - if (table_def_init() | hostname_cache_init()) + if (tdc_init() | hostname_cache_init()) unireg_abort(1); query_cache_set_min_res_unit(query_cache_min_res_unit); query_cache_init(); query_cache_resize(query_cache_size); + query_cache_result_size_limit(query_cache_limit); my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); setup_fpu(); init_thr_lock(); @@ -4407,7 +4895,7 @@ static int init_server_components() /* set up the hook before initializing plugins which may use it */ error_handler_hook= my_message_sql; - proc_info_hook= set_thd_proc_info; + proc_info_hook= set_thd_stage_info; #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE /* @@ -4421,6 +4909,15 @@ static int init_server_components() buffered_logs.cleanup(); #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ +#ifndef EMBEDDED_LIBRARY + /* + Now that the logger is available, redirect character set + errors directly to the logger + (instead of the buffered_logs used at the server startup time). + */ + my_charset_error_reporter= charset_error_reporter; +#endif + if (xid_cache_init()) { sql_print_error("Out of memory"); @@ -4462,56 +4959,19 @@ static int init_server_components() { if (opt_bin_log) { - sql_print_error("using --replicate-same-server-id in conjunction with \ ---log-slave-updates is impossible, it would lead to infinite loops in this \ -server."); + sql_print_error("using --replicate-same-server-id in conjunction with " + "--log-slave-updates is impossible, it would lead to " + "infinite loops in this server."); unireg_abort(1); } else - sql_print_warning("using --replicate-same-server-id in conjunction with \ ---log-slave-updates would lead to infinite loops in this server. However this \ -will be ignored as the --log-bin option is not defined."); + sql_print_warning("using --replicate-same-server-id in conjunction with " + "--log-slave-updates would lead to infinite loops in " + "this server. However this will be ignored as the " + "--log-bin option is not defined."); } #endif -#ifdef WITH_WSREP /* WSREP BEFORE SE */ - if (!wsrep_recovery && !opt_help) - { - if (opt_bootstrap) // bootsrap option given - disable wsrep functionality - { - wsrep_provider_init(WSREP_NONE); - if (wsrep_init()) unireg_abort(1); - } - else // full wsrep initialization - { - // add basedir/bin to PATH to resolve wsrep script names - char* const tmp_path((char*)alloca(strlen(mysql_home) + - strlen("/bin") + 1)); - if (tmp_path) - { - strcpy(tmp_path, mysql_home); - strcat(tmp_path, "/bin"); - wsrep_prepend_PATH(tmp_path); - } - else - { - WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); - } - - if (wsrep_before_SE()) - { -#ifndef EMBEDDED_LIBRARY - set_ports(); // this is also called in network_init() later but we need - // to know mysqld_port now - lp:1071882 -#endif /* !EMBEDDED_LIBRARY */ - - wsrep_init_startup(true); - } - } - } -#endif /* WITH_WSREP */ - DBUG_ASSERT(!opt_bin_log || opt_bin_logname); - if (opt_bin_log) { /* Reports an error and aborts, if the --log-bin's path @@ -4519,8 +4979,8 @@ will be ignored as the --log-bin option is not defined."); if (opt_bin_logname[0] && opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR) { - sql_print_error("Path '%s' is a directory name, please specify \ -a file name for --log-bin option", opt_bin_logname); + sql_print_error("Path '%s' is a directory name, please specify " + "a file name for --log-bin option", opt_bin_logname); unireg_abort(1); } @@ -4530,8 +4990,9 @@ a file name for --log-bin option", opt_bin_logname); opt_binlog_index_name[strlen(opt_binlog_index_name) - 1] == FN_LIBCHAR) { - sql_print_error("Path '%s' is a directory name, please specify \ -a file name for --log-bin-index option", opt_binlog_index_name); + sql_print_error("Path '%s' is a directory name, please specify " + "a file name for --log-bin-index option", + opt_binlog_index_name); unireg_abort(1); } @@ -4559,10 +5020,72 @@ a file name for --log-bin-index option", opt_binlog_index_name); { opt_bin_logname= my_once_strdup(buf, MYF(MY_WME)); } +#ifdef WITH_WSREP /* WSREP BEFORE SE */ + /* + Wsrep initialization must happen at this point, because: + - opt_bin_logname must be known when starting replication + since SST may need it + - SST may modify binlog index file, so it must be opened + after SST has happened + */ + } + if (!wsrep_recovery && !opt_help) + { + if (opt_bootstrap) // bootsrap option given - disable wsrep functionality + { + wsrep_provider_init(WSREP_NONE); + if (wsrep_init()) unireg_abort(1); + } + else // full wsrep initialization + { + // add basedir/bin to PATH to resolve wsrep script names + char* const tmp_path((char*)alloca(strlen(mysql_home) + + strlen("/bin") + 1)); + if (tmp_path) + { + strcpy(tmp_path, mysql_home); + strcat(tmp_path, "/bin"); + wsrep_prepend_PATH(tmp_path); + } + else + { + WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); + } + + if (wsrep_before_SE()) + { + set_ports(); // this is also called in network_init() later but we need + // to know mysqld_port now - lp:1071882 + /* + Plugin initialization (plugin_init()) hasn't happened yet, set + maria_hton to 0. + */ + maria_hton= 0; + wsrep_init_startup(true); + } + } + } + if (opt_bin_log) + { + /* + Variable ln is not defined at this scope. We use opt_bin_logname instead. + It should be the same as ln since + - mysql_bin_log.generate_name() returns first argument if new log name + is not generated + - if new log name is generated, return value is assigned to ln and copied + to opt_bin_logname above + */ + if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname, + TRUE)) + { + unireg_abort(1); + } +#else if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE)) { unireg_abort(1); } +#endif /* WITH_WSREP */ } /* call ha_init_key_cache() on all key caches to init them */ @@ -4614,12 +5137,12 @@ a file name for --log-bin-index option", opt_binlog_index_name); variables that allocates memory for this THD. */ THD *current_thd_saved= current_thd; - my_pthread_setspecific_ptr(THR_THD, tmp); + set_current_thd(tmp); tmp->init_for_queries(); /* Restore current_thd. */ - my_pthread_setspecific_ptr(THR_THD, current_thd_saved); + set_current_thd(current_thd_saved); tmp->server_status= server_status_saved; tmp->variables.option_bits= option_bits_saved; @@ -4629,13 +5152,6 @@ a file name for --log-bin-index option", opt_binlog_index_name); } #endif - have_csv= plugin_status(STRING_WITH_LEN("csv"), - MYSQL_STORAGE_ENGINE_PLUGIN); - have_ndbcluster= plugin_status(STRING_WITH_LEN("ndbcluster"), - MYSQL_STORAGE_ENGINE_PLUGIN); - have_partitioning= plugin_status(STRING_WITH_LEN("partition"), - MYSQL_STORAGE_ENGINE_PLUGIN); - /* we do want to exit if there are any other unknown options */ if (remaining_argc > 1) { @@ -4721,7 +5237,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", @@ -4749,7 +5265,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); global_system_variables.table_plugin= plugin; mysql_mutex_unlock(&LOCK_global_system_variables); } -#if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_ARIA_FOR_TMP_TABLES) +#ifdef USE_ARIA_FOR_TMP_TABLES if (!ha_storage_engine_is_enabled(maria_hton) && !opt_bootstrap) { sql_print_error("Aria engine is not enabled or did not start. The Aria engine must be enabled to continue as mysqld was configured with --with-aria-tmp-tables"); @@ -4774,6 +5290,12 @@ a file name for --log-bin-index option", opt_binlog_index_name); #ifdef WITH_WSREP if (WSREP_ON && tc_log == &tc_log_mmap) tc_log= &tc_log_dummy; + + WSREP_DEBUG("Initial TC log open: %s", + (tc_log == &mysql_bin_log) ? "binlog" : + (tc_log == &tc_log_mmap) ? "mmap" : + (tc_log == &tc_log_dummy) ? "dummy" : "unknown" + ); #endif if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) @@ -4788,7 +5310,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 @@ -4830,8 +5352,13 @@ 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); + init_status_vars(); DBUG_RETURN(0); } + + #ifndef EMBEDDED_LIBRARY static void create_shutdown_thread() @@ -4874,7 +5401,7 @@ pthread_handler_t start_wsrep_THD(void *arg) thread_created++; threads.append(thd); - my_net_init(&thd->net,(st_vio*) 0); + my_net_init(&thd->net,(st_vio*) 0, MYF(0)); DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); @@ -4928,7 +5455,7 @@ pthread_handler_t start_wsrep_THD(void *arg) /* handle_one_connection() again... */ //thd->version= refresh_version; thd->proc_info= 0; - thd->command= COM_SLEEP; + thd->set_command(COM_SLEEP); if (wsrep_creating_startup_threads == 0) { @@ -4998,7 +5525,7 @@ static bool abort_replicated(THD *thd) bool ret_code= false; if (thd->wsrep_query_state== QUERY_COMMITTING) { - if (wsrep_debug) WSREP_INFO("aborting replicated trx: %lu", thd->real_id); + WSREP_DEBUG("aborting replicated trx: %lu", thd->real_id); (void)wsrep_abort_thd(thd, thd, TRUE); ret_code= true; @@ -5099,7 +5626,6 @@ static my_bool have_committing_connections() if (is_committing_connection(tmp)) { - mysql_mutex_unlock(&LOCK_thread_count); return TRUE; } } @@ -5184,8 +5710,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) } DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); - if (wsrep_debug) - WSREP_INFO("waiting for client connections to close: %u", thread_count); + WSREP_DEBUG("waiting for client connections to close: %u", thread_count); while (wait_to_end && have_client_connections()) { @@ -5227,28 +5752,6 @@ static void wsrep_close_threads(THD *thd) mysql_mutex_unlock(&LOCK_thread_count); } -void wsrep_close_applier_threads(int count) -{ - THD *tmp; - mysql_mutex_lock(&LOCK_thread_count); // For unlink from list - - I_List_iterator<THD> it(threads); - while ((tmp=it++) && count) - { - DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); - /* We skip slave threads & scheduler on this first loop through. */ - if (tmp->wsrep_applier) - { - WSREP_DEBUG("closing wsrep applier thread %ld", tmp->thread_id); - tmp->wsrep_applier_closing= TRUE; - count--; - } - } - - mysql_mutex_unlock(&LOCK_thread_count); -} - void wsrep_wait_appliers_close(THD *thd) { /* Wait for wsrep appliers to gracefully exit */ @@ -5458,6 +5961,7 @@ static void test_lc_time_sz() } #endif//DBUG_OFF + #ifdef __WIN__ int win_main(int argc, char **argv) #else @@ -5470,6 +5974,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 @@ -5481,9 +5987,6 @@ int mysqld_main(int argc, char **argv) return 1; } #endif -#ifdef WITH_WSREP - wsrep_filter_new_cluster (&argc, argv); -#endif /* WITH_WSREP */ orig_argc= argc; orig_argv= argv; @@ -5504,38 +6007,33 @@ int mysqld_main(int argc, char **argv) #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE /* - The performance schema needs to be initialized as early as possible, - before to-be-instrumented objects of the server are initialized. + Initialize the array of performance schema instrument configurations. */ - int ho_error; - DYNAMIC_ARRAY all_early_options; - - my_getopt_register_get_addr(NULL); - /* Skip unknown options so that they may be processed later */ - my_getopt_skip_unknown= TRUE; - - /* prepare all_early_options array */ - my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25); - sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY); - add_terminator(&all_early_options); - + init_pfs_instrument_array(); +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ /* Logs generated while parsing the command line options are buffered and printed later. */ buffered_logs.init(); my_getopt_error_reporter= buffered_option_error_reporter; + my_charset_error_reporter= buffered_option_error_reporter; +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + pfs_param.m_pfs_instrument= const_cast<char*>(""); +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ - ho_error= handle_options(&remaining_argc, &remaining_argv, - (my_option*)(all_early_options.buffer), NULL); - delete_dynamic(&all_early_options); + int ho_error __attribute__((unused))= handle_early_options(); + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE if (ho_error == 0) { - /* Add back the program name handle_options removes */ - remaining_argc++; - remaining_argv--; - if (pfs_param.m_enabled) + if (pfs_param.m_enabled && !opt_help && !opt_bootstrap) { + /* Add sizing hints from the server sizing parameters. */ + pfs_param.m_hints.m_table_definition_cache= tdc_size; + pfs_param.m_hints.m_table_open_cache= tc_size; + pfs_param.m_hints.m_max_connections= max_connections; + pfs_param.m_hints.m_open_files_limit= open_files_limit; PSI_hook= initialize_performance_schema(&pfs_param); if (PSI_hook == NULL) { @@ -5563,27 +6061,29 @@ int mysqld_main(int argc, char **argv) if available. */ if (PSI_hook) - PSI_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION); - - if (PSI_server) { - /* - Now that we have parsed the command line arguments, and have initialized - the performance schema itself, the next step is to register all the - server instruments. - */ - init_server_psi_keys(); - /* Instrument the main thread */ - PSI_thread *psi= PSI_server->new_thread(key_thread_main, NULL, 0); - if (psi) - PSI_server->set_thread(psi); + PSI *psi_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION); + if (likely(psi_server != NULL)) + { + set_psi_server(psi_server); - /* - Now that some instrumentation is in place, - recreate objects which were initialised early, - so that they are instrumented as well. - */ - my_thread_global_reinit(); + /* + Now that we have parsed the command line arguments, and have + initialized the performance schema itself, the next step is to + register all the server instruments. + */ + init_server_psi_keys(); + /* Instrument the main thread */ + PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_main, NULL, 0); + PSI_THREAD_CALL(set_thread)(psi); + + /* + Now that some instrumentation is in place, + recreate objects which were initialised early, + so that they are instrumented as well. + */ + my_thread_global_reinit(); + } } #endif /* HAVE_PSI_INTERFACE */ @@ -5668,9 +6168,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; " @@ -5703,12 +6203,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; - #ifdef WITH_WSREP /* WSREP AFTER SE */ if (wsrep_recovery) { @@ -5717,6 +6211,7 @@ int mysqld_main(int argc, char **argv) unireg_abort(0); } #endif /* WITH_WSREP */ + /* init signals & alarm After this we can't quit by a simple unireg_abort @@ -5733,7 +6228,7 @@ int mysqld_main(int argc, char **argv) delete_pid_file(MYF(MY_WME)); - if (unix_sock != INVALID_SOCKET) + if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET) unlink(mysqld_unix_port); exit(1); } @@ -5741,26 +6236,12 @@ int mysqld_main(int argc, char **argv) if (!opt_noacl) (void) grant_init(); - if (!opt_bootstrap) - servers_init(0); - udf_init(); - init_status_vars(); if (opt_bootstrap) /* If running with bootstrap, do not start replication. */ 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); @@ -5778,17 +6259,18 @@ int mysqld_main(int argc, char **argv) execute_ddl_log_recovery(); - if (Events::init(opt_noacl || opt_bootstrap)) + /* + Change EVENTS_ORIGINAL to EVENTS_OFF (the default value) as there is no + point in using ORIGINAL during startup + */ + if (Events::opt_event_scheduler == Events::EVENTS_ORIGINAL) + Events::opt_event_scheduler= Events::EVENTS_OFF; + + Events::set_original_state(Events::opt_event_scheduler); + if (Events::init((THD*) 0, opt_noacl || opt_bootstrap)) unireg_abort(1); #ifdef WITH_WSREP /* WSREP AFTER SE */ - if (wsrep_recovery) - { - select_thread_in_use= 0; - wsrep_recover(); - unireg_abort(0); - } - if (opt_bootstrap) { /*! bootstrap wsrep init was taken care of above */ @@ -5813,7 +6295,7 @@ int mysqld_main(int argc, char **argv) wsrep_create_appliers(wsrep_slave_threads - 1); } #endif /* WITH_WSREP */ - if (opt_bootstrap) + if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work bootstrap(mysql_stdin); @@ -5825,31 +6307,58 @@ 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); } - 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), + ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ? + (char*) "" : mysqld_unix_port), mysqld_port, MYSQL_COMPILATION_COMMENT); + + // try to keep fd=0 busy + if (!freopen(IF_WIN("NUL","/dev/null"), "r", stdin)) + { + // fall back on failure + fclose(stdin); + } + #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) Service.SetRunning(); #endif - /* Signal threads waiting for server to be started */ mysql_mutex_lock(&LOCK_server_started); mysqld_server_started= 1; mysql_cond_signal(&COND_server_started); mysql_mutex_unlock(&LOCK_server_started); + MYSQL_SET_STAGE(0 ,__FILE__, __LINE__); + #if defined(_WIN32) || defined(HAVE_SMEM) handle_connections_methods(); #else @@ -5877,13 +6386,12 @@ int mysqld_main(int argc, char **argv) #endif #endif /* __WIN__ */ -#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_PSI_THREAD_INTERFACE /* Disable the main thread instrumentation, to avoid recording events during the shutdown. */ - if (PSI_server) - PSI_server->delete_current_thread(); + PSI_THREAD_CALL(delete_current_thread)(); #endif /* Wait until cleanup is done */ @@ -6137,11 +6645,11 @@ static void bootstrap(MYSQL_FILE *file) thd->variables.wsrep_on= 0; #endif 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; @@ -6225,55 +6733,70 @@ 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); + statistic_increment(connection_errors_internal, &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; } @@ -6310,6 +6833,7 @@ static void create_new_thread(THD *thd) close_connection(thd, ER_CON_COUNT_ERROR); statistic_increment(denied_connections, &LOCK_status); delete thd; + statistic_increment(connection_errors_max_connection, &LOCK_status); DBUG_VOID_RETURN; } @@ -6320,10 +6844,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. @@ -6331,8 +6855,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; @@ -6344,8 +6866,9 @@ static void create_new_thread(THD *thd) inline void kill_broken_server() { /* hack to get around signals ignored in syscalls for problem OS's */ - if (unix_sock == INVALID_SOCKET || - (!opt_disable_networking && base_ip_sock == INVALID_SOCKET)) + if (mysql_socket_getfd(unix_sock) == INVALID_SOCKET || + (!opt_disable_networking && + mysql_socket_getfd(base_ip_sock) == INVALID_SOCKET)) { select_thread_in_use = 0; /* The following call will never return */ @@ -6364,7 +6887,8 @@ inline void kill_broken_server() void handle_connections_sockets() { - my_socket UNINIT_VAR(sock), UNINIT_VAR(new_sock); + MYSQL_SOCKET sock= mysql_socket_invalid(); + MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; THD *thd; struct sockaddr_storage cAddr; @@ -6373,36 +6897,38 @@ void handle_connections_sockets() int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; st_vio *vio_tmp; + bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock + MYSQL_SOCKET pfs_fds[3]; // for performance schema #define setup_fds(X) \ - fds[socket_count].fd= X; \ + mysql_socket_set_thread_owner(X); \ + pfs_fds[socket_count]= (X); \ + fds[socket_count].fd= mysql_socket_getfd(X); \ fds[socket_count].events= POLLIN; \ socket_count++ #else +#define setup_fds(X) FD_SET(mysql_socket_getfd(X),&clientFDs) fd_set readFDs,clientFDs; - uint max_used_connection= (uint) - max(max(base_ip_sock, unix_sock), extra_ip_sock) + 1; -#define setup_fds(X) FD_SET(X,&clientFDs) FD_ZERO(&clientFDs); #endif DBUG_ENTER("handle_connections_sockets"); - if (base_ip_sock != INVALID_SOCKET) + if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET) { setup_fds(base_ip_sock); - ip_flags = fcntl(base_ip_sock, F_GETFL, 0); + ip_flags = fcntl(mysql_socket_getfd(base_ip_sock), F_GETFL, 0); } - if (extra_ip_sock != INVALID_SOCKET) + if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET) { setup_fds(extra_ip_sock); - extra_ip_flags = fcntl(extra_ip_sock, F_GETFL, 0); + extra_ip_flags = fcntl(mysql_socket_getfd(extra_ip_sock), F_GETFL, 0); } #ifdef HAVE_SYS_UN_H setup_fds(unix_sock); - socket_flags=fcntl(unix_sock, F_GETFL, 0); + socket_flags=fcntl(mysql_socket_getfd(unix_sock), F_GETFL, 0); #endif DBUG_PRINT("general",("Waiting for connections.")); @@ -6413,14 +6939,19 @@ void handle_connections_sockets() retval= poll(fds, socket_count, -1); #else readFDs=clientFDs; - - retval= select((int) max_used_connection,&readFDs,0,0,0); + retval= select((int) 0,&readFDs,0,0,0); #endif if (retval < 0) { if (socket_errno != SOCKET_EINTR) { + /* + select(2)/poll(2) failed on the listening port. + There is not much details to report about the client, + increment the server global status variable. + */ + statistic_increment(connection_errors_accept, &LOCK_status); if (!select_errors++ && !abort_loop) /* purecov: inspected */ sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */ } @@ -6440,19 +6971,19 @@ void handle_connections_sockets() { if (fds[i].revents & POLLIN) { - sock= fds[i].fd; - flags= fcntl(sock, F_GETFL, 0); + sock= pfs_fds[i]; + flags= fcntl(mysql_socket_getfd(sock), F_GETFL, 0); break; } } #else // HAVE_POLL - if (FD_ISSET(base_ip_sock,&readFDs)) + if (FD_ISSET(mysql_socket_getfd(base_ip_sock),&readFDs)) { sock= base_ip_sock; flags= ip_flags; } else - if (FD_ISSET(extra_ip_sock,&readFDs)) + if (FD_ISSET(mysql_socket_getfd(extra_ip_sock),&readFDs)) { sock= extra_ip_sock; flags= extra_ip_flags; @@ -6468,18 +6999,19 @@ void handle_connections_sockets() if (!(test_flags & TEST_BLOCKING)) { #if defined(O_NONBLOCK) - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NONBLOCK); #elif defined(O_NDELAY) - fcntl(sock, F_SETFL, flags | O_NDELAY); + fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NDELAY); #endif } #endif /* NO_FCNTL_NONBLOCK */ for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++) { size_socket length= sizeof(struct sockaddr_storage); - new_sock= accept(sock, (struct sockaddr *)(&cAddr), - &length); - if (new_sock != INVALID_SOCKET || + new_sock= mysql_socket_accept(key_socket_client_connection, sock, + (struct sockaddr *)(&cAddr), + &length); + if (mysql_socket_getfd(new_sock) != INVALID_SOCKET || (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN)) break; MAYBE_BROKEN_SYSCALL; @@ -6487,16 +7019,25 @@ void handle_connections_sockets() if (!(test_flags & TEST_BLOCKING)) { if (retry == MAX_ACCEPT_RETRY - 1) - fcntl(sock, F_SETFL, flags); // Try without O_NONBLOCK + { + // Try without O_NONBLOCK + fcntl(mysql_socket_getfd(sock), F_SETFL, flags); + } } #endif } #if !defined(NO_FCNTL_NONBLOCK) if (!(test_flags & TEST_BLOCKING)) - fcntl(sock, F_SETFL, flags); + fcntl(mysql_socket_getfd(sock), F_SETFL, flags); #endif - if (new_sock == INVALID_SOCKET) + if (mysql_socket_getfd(new_sock) == INVALID_SOCKET) { + /* + accept(2) failed on the listening port, after many retries. + There is not much details to report about the client, + increment the server global status variable. + */ + statistic_increment(connection_errors_accept, &LOCK_status); if ((error_count++ & 255) == 0) // This can happen often sql_perror("Error in accept"); MAYBE_BROKEN_SYSCALL; @@ -6505,16 +7046,18 @@ void handle_connections_sockets() continue; } #if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) - (void) fcntl(new_sock, F_SETFD, FD_CLOEXEC); + (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ #ifdef HAVE_LIBWRAP { - if (sock == base_ip_sock || sock == extra_ip_sock) + if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) || + mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) { struct request_info req; signal(SIGCHLD, SIG_DFL); - request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); + request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, + mysql_socket_getfd(new_sock), NULL); my_fromhost(&req); if (!my_hosts_access(&req)) { @@ -6536,42 +7079,42 @@ void handle_connections_sockets() ((void (*)(int))req.sink)(req.fd); (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) closesocket(new_sock); + (void) mysql_socket_close(new_sock); + /* + The connection was refused by TCP wrappers. + There are no details (by client IP) available to update the + host_cache. + */ + statistic_increment(connection_errors_tcpwrap, &LOCK_status); continue; } } } #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); + (void) mysql_socket_close(new_sock); + statistic_increment(connection_errors_internal, &LOCK_status); continue; } - 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)) + /* Set to get io buffers to be part of THD */ + set_current_thd(thd); + + is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); + + if (!(vio_tmp= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST: 0)) || + 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 @@ -6583,20 +7126,24 @@ void handle_connections_sockets() else { (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) closesocket(new_sock); + (void) mysql_socket_close(new_sock); } delete thd; + statistic_increment(connection_errors_internal, &LOCK_status); continue; } - if (sock == unix_sock) + + init_net_server_extension(thd); + if (is_unix_sock) thd->security_ctx->host=(char*) my_localhost; - if (sock == extra_ip_sock) + if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) { thd->extra_port= 1; thd->scheduler= extra_thread_scheduler; } create_new_thread(thd); + set_current_thd(0); } DBUG_VOID_RETURN; } @@ -6690,8 +7237,9 @@ 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; @@ -6700,6 +7248,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) /* 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; @@ -6879,6 +7428,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, @@ -6886,7 +7436,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; @@ -6895,6 +7445,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: @@ -6922,6 +7473,7 @@ errorconn: CloseHandle(event_conn_closed); delete thd; } + set_current_thd(0); /* End shared memory handling */ error: @@ -6952,6 +7504,64 @@ error: Handle start options ******************************************************************************/ + +/** + Process command line options flagged as 'early'. + Some components needs to be initialized as early as possible, + because the rest of the server initialization depends on them. + Options that needs to be parsed early includes: + - the performance schema, when compiled in, + - options related to the help, + - options related to the bootstrap + The performance schema needs to be initialized as early as possible, + before to-be-instrumented objects of the server are initialized. +*/ + +int handle_early_options() +{ + int ho_error; + DYNAMIC_ARRAY all_early_options; + + my_getopt_register_get_addr(NULL); + /* Skip unknown options so that they may be processed later */ + my_getopt_skip_unknown= TRUE; + + /* prepare all_early_options array */ + my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25, MYF(0)); + add_many_options(&all_early_options, pfs_early_options, + array_elements(pfs_early_options)); + sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY); + add_terminator(&all_early_options); + + ho_error= handle_options(&remaining_argc, &remaining_argv, + (my_option*)(all_early_options.buffer), + mysqld_get_one_option); + if (ho_error == 0) + { + /* Add back the program name handle_options removes */ + remaining_argc++; + remaining_argv--; + } + + delete_dynamic(&all_early_options); + + return ho_error; +} + + +#define MYSQL_COMPATIBILITY_OPTION(option) \ + { option, OPT_MYSQL_COMPATIBILITY, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + +#define MYSQL_TO_BE_IMPLEMENTED_OPTION(option) \ + { option, OPT_MYSQL_TO_BE_IMPLEMENTED, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + +#define MYSQL_SUGGEST_ANALOG_OPTION(option, str) \ + { option, OPT_MYSQL_COMPATIBILITY, \ + 0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 } + + /** System variables are automatically command-line options (few exceptions are documented in sys_var.h), so don't need @@ -6980,7 +7590,7 @@ struct my_option my_long_options[]= {"autocommit", 0, "Set default value for autocommit (0 or 1)", &opt_autocommit, &opt_autocommit, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL}, - {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.", + {"bind-address", 0, "IP address to bind to.", &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-do-db", OPT_BINLOG_DO_DB, @@ -7140,9 +7750,6 @@ struct my_option my_long_options[]= "Set the language used for the month names and the days of the week.", &lc_time_names_name, &lc_time_names_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"log", 'l', "Log connections and queries to file (deprecated option, use " - "--general-log/--general-log-file instead).", &opt_logname, &opt_logname, - 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-basename", OPT_LOG_BASENAME, "Basename for all log files and the .pid file. This sets all log file " "names at once (in 'datadir') and is normally the only option you need " @@ -7179,25 +7786,11 @@ struct my_option my_long_options[]= "Log slow statements executed by slave thread to the slow log if it is open.", &opt_log_slow_slave_statements, &opt_log_slow_slave_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slow-queries", OPT_SLOW_QUERY_LOG, - "Enable logging of slow queries (longer than --long-query-time) to log file " - "or table. Optional argument is a file name for the slow log. If not given, " - "'log-basename'-slow.log will be used. Use --log-output=TABLE if you want " - "to have the log in the table mysql.slow_log. " - "Deprecated option, use --slow-query-log/--slow-query-log-file instead.", - &opt_slow_logname, &opt_slow_logname, 0, GET_STR_ALLOC, OPT_ARG, - 0, 0, 0, 0, 0, 0}, {"log-tc", 0, "Path to transaction coordinator log (used for transactions that affect " "more than one storage engine, when binary log is disabled).", &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_MMAP - {"log-tc-size", 0, "Size of transaction coordinator log.", - &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG, - REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0, - TC_LOG_PAGE_SIZE, 0}, -#endif {"master-info-file", 0, "The location and name of the file that remembers the master and where " "the I/O replication thread is in the master's binlogs. Defaults to " @@ -7215,10 +7808,6 @@ struct my_option my_long_options[]= #endif /* HAVE_REPLICATION */ {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory, &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"one-thread", OPT_ONE_THREAD, - "(Deprecated): Only use one thread (for debugging under Linux). Use " - "thread-handling=no-threads instead.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"old-style-user-limits", 0, "Enable old-style user limits (before 5.0.3, user resources were counted " "per each user+host vs. per account).", @@ -7236,28 +7825,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. " @@ -7273,7 +7862,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 " @@ -7281,7 +7870,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, @@ -7306,10 +7895,6 @@ struct my_option my_long_options[]= {"skip-slave-start", 0, "If set, slave is not autostarted.", &opt_skip_slave_start, &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-thread-priority", OPT_SKIP_PRIOR, - "Don't give threads different priorities. This option is deprecated " - "because it has no effect; the implied behavior is already the default.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) {"slow-start-timeout", 0, "Maximum number of milliseconds that the service control manager should wait " @@ -7319,7 +7904,7 @@ struct my_option my_long_options[]= #endif #ifdef HAVE_OPENSSL {"ssl", 0, - "Enable SSL for connection (automatically enabled with other flags).", + "Enable SSL for connection (automatically enabled if an ssl option is used).", &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif @@ -7362,24 +7947,85 @@ struct my_option my_long_options[]= &global_system_variables.tx_isolation, &global_system_variables.tx_isolation, &tx_isolation_typelib, GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0}, + {"transaction-read-only", 0, + "Default transaction access mode. " + "True if transactions are read-only.", + &global_system_variables.tx_read_only, + &global_system_variables.tx_read_only, 0, + GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Used with --help option for detailed help.", &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"plugin-load", 0, + {"plugin-load", OPT_PLUGIN_LOAD, "Semicolon-separated list of plugins to load, where each plugin is " "specified as ether a plugin_name=library_file pair or only a library_file. " "If the latter case, all plugins from a given library_file will be loaded.", - &opt_plugin_load, &opt_plugin_load, 0, + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"plugin-load-add", OPT_PLUGIN_LOAD_ADD, + "Optional semicolon-separated list of plugins to load. This option adds " + "to the list specified by --plugin-load in an incremental way. " + "It can be specified many times, adding more plugins every time.", + 0, 0, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"table_cache", 0, "Deprecated; use --table-open-cache instead.", - &table_cache_size, &table_cache_size, 0, GET_ULONG, + &tc_size, &tc_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} -}; +#ifdef WITH_WSREP + {"wsrep-new-cluster", 0, "Bootstrap a cluster. It works by overriding the " + "current value of wsrep_cluster_address. It is recommended not to add this " + "option to the config file as this will trigger bootstrap on every server " + "start.", &wsrep_new_cluster, &wsrep_new_cluster, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, +#endif + /* The following options exist in 5.6 but not in 10.0 */ + MYSQL_TO_BE_IMPLEMENTED_OPTION("default-tmp-storage-engine"), + MYSQL_COMPATIBILITY_OPTION("log-raw"), + MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"), + MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("binlog-row-image"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("explicit-defaults-for-timestamp"), + MYSQL_COMPATIBILITY_OPTION("master-info-repository"), + MYSQL_COMPATIBILITY_OPTION("relay-log-info-repository"), + MYSQL_SUGGEST_ANALOG_OPTION("binlog-rows-query-log-events", "--binlog-annotate-row-events"), + MYSQL_COMPATIBILITY_OPTION("binlog-order-commits"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("log-throttle-queries-not-using-indexes"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("end-markers-in-json"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-features"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-offset"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-limit"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-max-mem-size"), // OPTIMIZER_TRACE + MYSQL_TO_BE_IMPLEMENTED_OPTION("eq-range-index-dive-limit"), + MYSQL_COMPATIBILITY_OPTION("server-id-bits"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-rows-search-algorithms"), // HAVE_REPLICATION + MYSQL_COMPATIBILITY_OPTION("table-open-cache-instances"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-allow-batching"), // HAVE_REPLICATION + MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-period"), // HAVE_REPLICATION + MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-group"), // HAVE_REPLICATION + MYSQL_SUGGEST_ANALOG_OPTION("slave-parallel-workers", "--slave-parallel-threads"), // HAVE_REPLICATION + MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"), // HAVE_REPLICATION + MYSQL_TO_BE_IMPLEMENTED_OPTION("disconnect-on-expired-password"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-private-key-path"), // HAVE_OPENSSL && !HAVE_YASSL + MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-public-key-path"), // HAVE_OPENSSL && !HAVE_YASSL + + /* The following options exist in 5.5 and 5.6 but not in 10.0 */ + MYSQL_SUGGEST_ANALOG_OPTION("abort-slave-event-count", "--debug-abort-slave-event-count"), + MYSQL_SUGGEST_ANALOG_OPTION("disconnect-slave-event-count", "--debug-disconnect-slave-event-count"), + MYSQL_SUGGEST_ANALOG_OPTION("exit-info", "--debug-exit-info"), + MYSQL_SUGGEST_ANALOG_OPTION("max-binlog-dump-events", "--debug-max-binlog-dump-events"), + MYSQL_SUGGEST_ANALOG_OPTION("sporadic-binlog-dump-fail", "--debug-sporadic-binlog-dump-fail"), + MYSQL_COMPATIBILITY_OPTION("new"), + + /* The following options were added after 5.6.10 */ + MYSQL_TO_BE_IMPLEMENTED_OPTION("rpl-stop-slave-timeout"), + MYSQL_TO_BE_IMPLEMENTED_OPTION("validate-user-plugins") // NO_EMBEDDED_ACCESS_CHECKS +}; static int show_queries(THD *thd, SHOW_VAR *var, char *buff) { @@ -7424,52 +8070,109 @@ 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= NULL; + bool tmp; + LINT_INIT(tmp); + var->type= SHOW_MY_BOOL; 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_lock(&LOCK_active_mi); + if (master_info_index) + { + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE); + if (mi) + tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING && + mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); + } + mysql_mutex_unlock(&LOCK_active_mi); + if (mi) + *((my_bool *)buff)= tmp; + else + var->type= SHOW_UNDEF; return 0; } -static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff) + +/* How many slaves are connected to this master */ + +static int show_slaves_connected(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. - */ - if (active_mi) - { - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (long)active_mi->rli.retried_trans; - } - else - var->type= SHOW_UNDEF; + + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_lock(&LOCK_slave_list); + + *((longlong *)buff)= slave_list.records; + + mysql_mutex_unlock(&LOCK_slave_list); + return 0; +} + + +/* How many masters this slave is connected to */ + + +static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_lock(&LOCK_active_mi); + + *((longlong *)buff)= master_info_index->any_slave_sql_running(); + + mysql_mutex_unlock(&LOCK_active_mi); return 0; } + static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff) { - if (active_mi) - { - var->type= SHOW_LONGLONG; - var->value= buff; - *((longlong *)buff)= active_mi->received_heartbeats; - } + Master_info *mi= NULL; + longlong tmp; + LINT_INIT(tmp); + + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_lock(&LOCK_active_mi); + if (master_info_index) + { + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE); + if (mi) + tmp= mi->received_heartbeats; + } + mysql_mutex_unlock(&LOCK_active_mi); + if (mi) + *((longlong *)buff)= tmp; else var->type= SHOW_UNDEF; return 0; } + static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) { - if (active_mi) - { - var->type= SHOW_CHAR; - var->value= buff; - sprintf(buff, "%.3f", active_mi->heartbeat_period); - } + Master_info *mi= NULL; + float tmp; + LINT_INIT(tmp); + + var->type= SHOW_CHAR; + var->value= buff; + mysql_mutex_lock(&LOCK_active_mi); + if (master_info_index) + { + mi= master_info_index-> + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE); + if (mi) + tmp= mi->heartbeat_period; + } + mysql_mutex_unlock(&LOCK_active_mi); + if (mi) + sprintf(buff, "%.3f", tmp); else var->type= SHOW_UNDEF; return 0; @@ -7482,7 +8185,7 @@ static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_LONG; var->value= buff; - *((long *)buff)= (long)cached_open_tables(); + *((long *) buff)= (long) tc_records(); return 0; } @@ -7500,10 +8203,20 @@ static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_LONG; var->value= buff; - *((long *)buff)= (long)cached_table_definitions(); + *((long *) buff)= (long) tdc_records(); return 0; } + +static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *) buff)= (long) tdc_refresh_version(); + return 0; +} + + #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) /* Functions relying on CTX */ static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff) @@ -7760,6 +8473,110 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff) return 0; } + +#ifdef HAVE_YASSL + +static char * +my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len) +{ + return yaSSL_ASN1_TIME_to_string(time, buf, len); +} + +#else /* openssl */ + +static char * +my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len) +{ + int n_read; + char *res= NULL; + BIO *bio= BIO_new(BIO_s_mem()); + + if (bio == NULL) + return NULL; + + if (!ASN1_TIME_print(bio, time)) + goto end; + + n_read= BIO_read(bio, buf, (int) (len - 1)); + + if (n_read > 0) + { + buf[n_read]= 0; + res= buf; + } + +end: + BIO_free(bio); + return res; +} + +#endif + + +/** + Handler function for the 'ssl_get_server_not_before' variable + + @param thd the mysql thread structure + @param var the data for the variable + @param[out] buf the string to put the value of the variable into + + @return status + @retval 0 success +*/ + +static int +show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + if(thd->vio_ok() && thd->net.vio->ssl_arg) + { + SSL *ssl= (SSL*) thd->net.vio->ssl_arg; + X509 *cert= SSL_get_certificate(ssl); + ASN1_TIME *not_before= X509_get_notBefore(cert); + + var->value= my_asn1_time_to_string(not_before, buff, + SHOW_VAR_FUNC_BUFF_SIZE); + if (!var->value) + return 1; + var->value= buff; + } + else + var->value= empty_c_string; + return 0; +} + + +/** + Handler function for the 'ssl_get_server_not_after' variable + + @param thd the mysql thread structure + @param var the data for the variable + @param[out] buf the string to put the value of the variable into + + @return status + @retval 0 success +*/ + +static int +show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_CHAR; + if(thd->vio_ok() && thd->net.vio->ssl_arg) + { + SSL *ssl= (SSL*) thd->net.vio->ssl_arg; + X509 *cert= SSL_get_certificate(ssl); + ASN1_TIME *not_after= X509_get_notAfter(cert); + + var->value= my_asn1_time_to_string(not_after, buff, + SHOW_VAR_FUNC_BUFF_SIZE); + if (!var->value) + return 1; + } + else + var->value= empty_c_string; + return 0; +} + #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff) @@ -7802,6 +8619,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) { @@ -7829,35 +8682,46 @@ 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}, + {"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG}, + {"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG}, + {"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG}, + {"Connection_errors_peer_address", (char*) &connection_errors_peer_addr, SHOW_LONG}, + {"Connection_errors_select", (char*) &connection_errors_select, SHOW_LONG}, + {"Connection_errors_tcpwrap", (char*) &connection_errors_tcpwrap, SHOW_LONG}, {"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_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}, + {"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}, {"Empty_queries", (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS}, {"Executed_events", (char*) &executed_events, SHOW_LONG_NOFLUSH }, {"Executed_triggers", (char*) offsetof(STATUS_VAR, executed_triggers), SHOW_LONG_STATUS}, + {"Feature_delay_key_write", (char*) &feature_files_opened_with_delayed_keys, SHOW_LONG }, {"Feature_dynamic_columns", (char*) offsetof(STATUS_VAR, feature_dynamic_columns), SHOW_LONG_STATUS}, {"Feature_fulltext", (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS}, {"Feature_gis", (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS}, {"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}, - {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH}, + {"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*) &show_flush_commands, SHOW_SIMPLE_FUNC}, {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS}, + {"Handler_external_lock", (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS}, {"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}, @@ -7877,18 +8741,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}, @@ -7900,54 +8766,60 @@ 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}, -#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}, + {"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_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}, + {"Slaves_connected", (char*) &show_slaves_connected, SHOW_SIMPLE_FUNC }, + {"Slaves_running", (char*) &show_slaves_running, SHOW_SIMPLE_FUNC }, + {"Slave_connections", (char*) offsetof(STATUS_VAR, com_register_slave), SHOW_LONG_STATUS}, + {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC}, + {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC}, + {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG}, + {"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}, - {"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS}, - {"Sort_range", (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS}, - {"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS}, - {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS}, + {"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes_), SHOW_LONG_STATUS}, + {"Sort_priority_queue_sorts",(char*) offsetof(STATUS_VAR, filesort_pq_sorts_), SHOW_LONG_STATUS}, + {"Sort_range", (char*) offsetof(STATUS_VAR, filesort_range_count_), SHOW_LONG_STATUS}, + {"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows_), SHOW_LONG_STATUS}, + {"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_server_not_after", (char*) &show_ssl_get_server_not_after, SHOW_SIMPLE_FUNC}, + {"Ssl_server_not_before", (char*) &show_ssl_get_server_not_before, 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}, @@ -7965,16 +8837,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 #ifdef WITH_WSREP {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL}, @@ -7984,7 +8856,7 @@ SHOW_VAR status_vars[]= { {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH}, {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH}, - {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC}, + {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_SIMPLE_FUNC}, {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR}, {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR}, {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR}, @@ -7994,12 +8866,21 @@ SHOW_VAR status_vars[]= { {NullS, NullS, SHOW_LONG} }; -bool add_terminator(DYNAMIC_ARRAY *options) +static bool add_terminator(DYNAMIC_ARRAY *options) { my_option empty_element= {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}; return insert_dynamic(options, (uchar *)&empty_element); } +static bool add_many_options(DYNAMIC_ARRAY *options, my_option *list, + size_t elements) +{ + for (my_option *opt= list; opt < list + elements; opt++) + if (insert_dynamic(options, opt)) + return 1; + return 0; +} + #ifndef EMBEDDED_LIBRARY static void print_version(void) { @@ -8031,22 +8912,30 @@ static int option_cmp(my_option *a, my_option *b) return 1; } } - DBUG_ASSERT(a->name == b->name); return 0; } 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); + add_many_options(&all_options, pfs_early_options, + array_elements(pfs_early_options)); sys_var_add_options(&all_options, sys_var::PARSE_EARLY); add_plugin_options(&all_options, &mem_root); sort_dynamic(&all_options, (qsort_cmp) option_cmp); + sort_dynamic(&all_options, (qsort_cmp) option_cmp); add_terminator(&all_options); my_print_help((my_option*) all_options.buffer); + + /* Add variables that can be shown but not changed, like version numbers */ + pop_dynamic(&all_options); + sys_var_add_options(&all_options, sys_var::SHOW_VALUE_IN_HELP); + sort_dynamic(&all_options, (qsort_cmp) option_cmp); + add_terminator(&all_options); my_print_variables((my_option*) all_options.buffer); free_root(&mem_root, MYF(0)); @@ -8070,16 +8959,15 @@ static void usage(void) else { #ifdef __WIN__ - puts("NT and Win32 specific options:\n\ - --install Install the default service (NT).\n\ - --install-manual Install the default service started manually (NT).\n\ - --install service_name Install an optional service (NT).\n\ - --install-manual service_name Install an optional service started manually (NT).\n\ - --remove Remove the default service from the service list (NT).\n\ - --remove service_name Remove the service_name from the service list (NT).\n\ - --enable-named-pipe Only to be used for the default server (NT).\n\ - --standalone Dummy option to start as a standalone server (NT).\ -"); + puts("NT and Win32 specific options:\n" + " --install Install the default service (NT).\n" + " --install-manual Install the default service started manually (NT).\n" + " --install service_name Install an optional service (NT).\n" + " --install-manual service_name Install an optional service started manually (NT).\n" + " --remove Remove the default service from the service list (NT).\n" + " --remove service_name Remove the service_name from the service list (NT).\n" + " --enable-named-pipe Only to be used for the default server (NT).\n" + " --standalone Dummy option to start as a standalone server (NT)."); puts(""); #endif print_defaults(MYSQL_CONFIG_NAME,load_default_groups); @@ -8091,14 +8979,12 @@ static void usage(void) if (! plugins_are_initialized) { - puts("\n\ -Plugins have parameters that are not reflected in this list\n\ -because execution stopped before plugins were initialized."); + puts("\nPlugins have parameters that are not reflected in this list" + "\nbecause execution stopped before plugins were initialized."); } - puts("\n\ -To see what values a running MySQL server is using, type\n\ -'mysqladmin variables' instead of 'mysqld --verbose --help'."); + puts("\nTo see what values a running MySQL server is using, type" + "\n'mysqladmin variables' instead of 'mysqld --verbose --help'."); } DBUG_VOID_RETURN; } @@ -8141,7 +9027,8 @@ static int mysql_init_variables(void) cleanup_done= 0; server_id_supplied= 0; test_flags= select_errors= dropping_tables= ha_open_options=0; - thread_count= thread_running= kill_cached_threads= wake_thread=0; + thread_count= thread_running= kill_cached_threads= wake_thread= 0; + service_thread_count= 0; slave_open_temp_tables= 0; cached_thread_count= 0; opt_endinfo= using_udf_functions= 0; @@ -8175,17 +9062,20 @@ static int mysql_init_variables(void) character_set_filesystem= &my_charset_bin; opt_specialflag= SPECIAL_ENGLISH; - unix_sock= base_ip_sock= extra_ip_sock= INVALID_SOCKET; + unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET; mysql_home_ptr= mysql_home; pidfile_name_ptr= pidfile_name; log_error_file_ptr= log_error_file; 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); strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1); threads.empty(); thread_cache.empty(); @@ -8209,6 +9099,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; @@ -8233,8 +9124,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; @@ -8344,6 +9240,14 @@ mysqld_get_one_option(int optid, "for compatiblity with old my.cnf files.", opt->name); break; + case OPT_MYSQL_COMPATIBILITY: + sql_print_warning("'%s' is MySQL 5.6 compatible option. Not used or needed " + "in MariaDB.", opt->name); + break; + case OPT_MYSQL_TO_BE_IMPLEMENTED: + sql_print_warning("'%s' is MySQL 5.6 compatible option. To be implemented " + "in later versions.", opt->name); + break; case 'a': global_system_variables.sql_mode= MODE_ANSI; global_system_variables.tx_isolation= ISO_SERIALIZABLE; @@ -8355,10 +9259,6 @@ mysqld_get_one_option(int optid, if (default_collation_name == compiled_default_collation_name) default_collation_name= 0; break; - case 'l': - WARN_DEPRECATED(NULL, 7, 0, "--log", "'--general-log'/'--general-log-file'"); - opt_log=1; - break; case 'h': strmake_buf(mysql_real_data_home, argument); /* Correct pointer set by my_getopt (for embedded library) */ @@ -8402,7 +9302,7 @@ mysqld_get_one_option(int optid, opt_myisam_log=1; break; case (int) OPT_BIN_LOG: - opt_bin_log= test(argument != disabled_my_option); + opt_bin_log= MY_TEST(argument != disabled_my_option); opt_bin_log_used= 1; break; case (int) OPT_LOG_BASENAME: @@ -8436,12 +9336,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: @@ -8472,7 +9372,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; } @@ -8488,7 +9388,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; @@ -8497,7 +9397,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; @@ -8506,7 +9406,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; @@ -8515,7 +9415,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; @@ -8523,10 +9423,6 @@ mysqld_get_one_option(int optid, break; } #endif /* HAVE_REPLICATION */ - case (int) OPT_SLOW_QUERY_LOG: - WARN_DEPRECATED(NULL, 7, 0, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'"); - opt_slow_log= 1; - break; case (int) OPT_SAFE: opt_specialflag|= SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC; delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; @@ -8538,12 +9434,6 @@ mysqld_get_one_option(int optid, sql_print_warning("The syntax '--safe-mode' is deprecated and will be " "removed in a future release."); break; - 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 " - "as the implied behavior is already the default."); - break; case (int) OPT_SKIP_HOST_CACHE: opt_specialflag|= SPECIAL_NO_HOST_CACHE; break; @@ -8563,9 +9453,7 @@ mysqld_get_one_option(int optid, break; case OPT_SERVER_ID: server_id_supplied = 1; - break; - case OPT_ONE_THREAD: - thread_handling= SCHEDULER_NO_THREADS; + ::server_id= global_system_variables.server_id; break; case OPT_LOWER_CASE_TABLE_NAMES: lower_case_table_names_used= 1; @@ -8594,18 +9482,6 @@ mysqld_get_one_option(int optid, } break; #endif /* defined(ENABLED_DEBUG_SYNC) */ - case OPT_ENGINE_CONDITION_PUSHDOWN: - /* - The last of --engine-condition-pushdown and --optimizer_switch on - command line wins (see get_options(). - */ - if (global_system_variables.engine_condition_pushdown) - global_system_variables.optimizer_switch|= - OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; - else - global_system_variables.optimizer_switch&= - ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; - break; case OPT_LOG_ERROR: /* "No --log-error" == "write errors to stderr", @@ -8614,11 +9490,6 @@ mysqld_get_one_option(int optid, if (argument == NULL) /* no argument */ log_error_file_ptr= const_cast<char*>(""); break; - case OPT_MAX_LONG_DATA_SIZE: - max_long_data_size_used= true; - break; - - case OPT_IGNORE_DB_DIRECTORY: if (*argument == 0) ignore_db_dirs_reset(); @@ -8633,6 +9504,85 @@ mysqld_get_one_option(int optid, } } break; + + case OPT_PLUGIN_LOAD: + free_list(opt_plugin_load_list_ptr); + /* fall through */ + case OPT_PLUGIN_LOAD_ADD: + opt_plugin_load_list_ptr->push_back(new i_string(argument)); + break; + case OPT_MAX_LONG_DATA_SIZE: + max_long_data_size_used= true; + break; + case OPT_PFS_INSTRUMENT: +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#ifndef EMBEDDED_LIBRARY + /* Parse instrument name and value from argument string */ + char* name = argument,*p, *val; + + /* Assignment required */ + if (!(p= strchr(argument, '='))) + { + my_getopt_error_reporter(WARNING_LEVEL, + "Missing value for performance_schema_instrument " + "'%s'", argument); + return 0; + } + + /* Option value */ + val= p + 1; + if (!*val) + { + my_getopt_error_reporter(WARNING_LEVEL, + "Missing value for performance_schema_instrument " + "'%s'", argument); + return 0; + } + + /* Trim leading spaces from instrument name */ + while (*name && my_isspace(mysqld_charset, *name)) + name++; + + /* Trim trailing spaces and slashes from instrument name */ + while (p > argument && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '/')) + p--; + *p= 0; + + if (!*name) + { + my_getopt_error_reporter(WARNING_LEVEL, + "Invalid instrument name for " + "performance_schema_instrument '%s'", argument); + return 0; + } + + /* Trim leading spaces from option value */ + while (*val && my_isspace(mysqld_charset, *val)) + val++; + + /* Trim trailing spaces from option value */ + if ((p= my_strchr(mysqld_charset, val, val+strlen(val), ' ')) != NULL) + *p= 0; + + if (!*val) + { + my_getopt_error_reporter(WARNING_LEVEL, + "Invalid value for performance_schema_instrument " + "'%s'", argument); + return 0; + } + + /* Add instrument name and value to array of configuration options */ + if (add_pfs_instr_to_array(name, val)) + { + my_getopt_error_reporter(WARNING_LEVEL, + "Invalid value for performance_schema_instrument " + "'%s'", argument); + return 0; + } +#endif /* EMBEDDED_LIBRARY */ +#endif + break; } return 0; } @@ -8643,7 +9593,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) @@ -8654,9 +9604,10 @@ mysql_getopt_value(const char *keyname, uint key_length, case OPT_KEY_CACHE_DIVISION_LIMIT: case OPT_KEY_CACHE_AGE_THRESHOLD: case OPT_KEY_CACHE_PARTITIONS: + case OPT_KEY_CACHE_CHANGED_BLOCKS_HASH_SIZE: { 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; @@ -8673,8 +9624,26 @@ mysql_getopt_value(const char *keyname, uint key_length, return &key_cache->param_age_threshold; case OPT_KEY_CACHE_PARTITIONS: return (uchar**) &key_cache->param_partitions; + case OPT_KEY_CACHE_CHANGED_BLOCKS_HASH_SIZE: + return (uchar**) &key_cache->changed_blocks_hash_size; } } + 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; } @@ -8715,11 +9684,8 @@ 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); - for (my_option *opt= my_long_options; - opt < my_long_options + array_elements(my_long_options) - 1; - opt++) - insert_dynamic(&all_options, (uchar*) opt); + array_elements(my_long_options)/4, MYF(0)); + add_many_options(&all_options, my_long_options, array_elements(my_long_options)); sys_var_add_options(&all_options, 0); add_terminator(&all_options); @@ -8839,7 +9805,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; @@ -8875,7 +9841,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr) Set some global variables from the global_system_variables In most cases the global variables will not be used */ - my_disable_locking= myisam_single_user= test(opt_external_locking == 0); + my_disable_locking= myisam_single_user= MY_TEST(opt_external_locking == 0); my_default_record_cache_size=global_system_variables.read_buff_size; /* @@ -8932,8 +9898,8 @@ static int get_options(int *argc_ptr, char ***argv_ptr) #endif global_system_variables.engine_condition_pushdown= - test(global_system_variables.optimizer_switch & - OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN); + MY_TEST(global_system_variables.optimizer_switch & + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN); opt_readonly= read_only; @@ -8944,8 +9910,37 @@ 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; + } + } + + /* Ensure that some variables are not set higher than needed */ + if (back_log > max_connections) + back_log= max_connections; + if (thread_cache_size > max_connections) + thread_cache_size= max_connections; + return 0; } @@ -9197,8 +10192,6 @@ static int test_if_case_insensitive(const char *dir_name) DBUG_PRINT("exit", ("result: %d", result)); DBUG_RETURN(result); } - - #ifndef EMBEDDED_LIBRARY /** @@ -9256,7 +10249,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; @@ -9273,32 +10266,394 @@ 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); + max_used_connections= connection_count + extra_connection_count; } +#ifdef HAVE_PSI_INTERFACE +static PSI_file_info all_server_files[]= +{ +#ifdef HAVE_MMAP + { &key_file_map, "map", 0}, +#endif /* HAVE_MMAP */ + { &key_file_binlog, "binlog", 0}, + { &key_file_binlog_index, "binlog_index", 0}, + { &key_file_relaylog, "relaylog", 0}, + { &key_file_relaylog_index, "relaylog_index", 0}, + { &key_file_casetest, "casetest", 0}, + { &key_file_dbopt, "dbopt", 0}, + { &key_file_des_key_file, "des_key_file", 0}, + { &key_file_ERRMSG, "ERRMSG", 0}, + { &key_select_to_file, "select_to_file", 0}, + { &key_file_fileparser, "file_parser", 0}, + { &key_file_frm, "FRM", 0}, + { &key_file_global_ddl_log, "global_ddl_log", 0}, + { &key_file_load, "load", 0}, + { &key_file_loadfile, "LOAD_FILE", 0}, + { &key_file_log_event_data, "log_event_data", 0}, + { &key_file_log_event_info, "log_event_info", 0}, + { &key_file_master_info, "master_info", 0}, + { &key_file_misc, "misc", 0}, + { &key_file_partition, "partition", 0}, + { &key_file_pid, "pid", 0}, + { &key_file_query_log, "query_log", 0}, + { &key_file_relay_log_info, "relay_log_info", 0}, + { &key_file_send_file, "send_file", 0}, + { &key_file_slow_log, "slow_log", 0}, + { &key_file_tclog, "tclog", 0}, + { &key_file_trg, "trigger_name", 0}, + { &key_file_trn, "trigger", 0}, + { &key_file_init, "init", 0}, + { &key_file_binlog_state, "binlog_state", 0} +}; +#endif /* HAVE_PSI_INTERFACE */ + +PSI_stage_info stage_after_create= { 0, "After create", 0}; +PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0}; +PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0}; +PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0}; +PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0}; +PSI_stage_info stage_alter_inplace= { 0, "altering table", 0}; +PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0}; +PSI_stage_info stage_changing_master= { 0, "Changing master", 0}; +PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0}; +PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0}; +PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "checking privileges on cached query", 0}; +PSI_stage_info stage_checking_query_cache_for_query= { 0, "checking query cache for query", 0}; +PSI_stage_info stage_cleaning_up= { 0, "cleaning up", 0}; +PSI_stage_info stage_closing_tables= { 0, "closing tables", 0}; +PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0}; +PSI_stage_info stage_converting_heap_to_myisam= { 0, "converting HEAP to " TMP_ENGINE_NAME, 0}; +PSI_stage_info stage_copying_to_group_table= { 0, "Copying to group table", 0}; +PSI_stage_info stage_copying_to_tmp_table= { 0, "Copying to tmp table", 0}; +PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", 0}; +PSI_stage_info stage_creating_delayed_handler= { 0, "Creating delayed handler", 0}; +PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0}; +PSI_stage_info stage_creating_table= { 0, "creating table", 0}; +PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0}; +PSI_stage_info stage_deleting_from_main_table= { 0, "deleting from main table", 0}; +PSI_stage_info stage_deleting_from_reference_tables= { 0, "deleting from reference tables", 0}; +PSI_stage_info stage_discard_or_import_tablespace= { 0, "discard_or_import_tablespace", 0}; +PSI_stage_info stage_enabling_keys= { 0, "enabling keys", 0}; +PSI_stage_info stage_end= { 0, "end", 0}; +PSI_stage_info stage_executing= { 0, "executing", 0}; +PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0}; +PSI_stage_info stage_explaining= { 0, "explaining", 0}; +PSI_stage_info stage_finding_key_cache= { 0, "Finding key cache", 0}; +PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0}; +PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0}; +PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0}; +PSI_stage_info stage_freeing_items= { 0, "freeing items", 0}; +PSI_stage_info stage_fulltext_initialization= { 0, "FULLTEXT initialization", 0}; +PSI_stage_info stage_got_handler_lock= { 0, "got handler lock", 0}; +PSI_stage_info stage_got_old_table= { 0, "got old table", 0}; +PSI_stage_info stage_init= { 0, "init", 0}; +PSI_stage_info stage_insert= { 0, "insert", 0}; +PSI_stage_info stage_invalidating_query_cache_entries_table= { 0, "invalidating query cache entries (table)", 0}; +PSI_stage_info stage_invalidating_query_cache_entries_table_list= { 0, "invalidating query cache entries (table list)", 0}; +PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0}; +PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0}; +PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE.", 0}; +PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE.", 0}; +PSI_stage_info stage_manage_keys= { 0, "manage keys", 0}; +PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for binlog to be updated", 0}; +PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0}; +PSI_stage_info stage_optimizing= { 0, "optimizing", 0}; +PSI_stage_info stage_preparing= { 0, "preparing", 0}; +PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0}; +PSI_stage_info stage_query_end= { 0, "query end", 0}; +PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0}; +PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0}; +PSI_stage_info stage_recreating_table= { 0, "recreating table", 0}; +PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0}; +PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0}; +PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0}; +PSI_stage_info stage_rename= { 0, "rename", 0}; +PSI_stage_info stage_rename_result_table= { 0, "rename result table", 0}; +PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0}; +PSI_stage_info stage_reschedule= { 0, "reschedule", 0}; +PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0}; +PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0}; +PSI_stage_info stage_sending_cached_result_to_client= { 0, "sending cached result to client", 0}; +PSI_stage_info stage_sending_data= { 0, "Sending data", 0}; +PSI_stage_info stage_setup= { 0, "setup", 0}; +PSI_stage_info stage_show_explain= { 0, "show explain", 0}; +PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for the slave I/O thread to update it", 0}; +PSI_stage_info stage_sorting= { 0, "Sorting", 0}; +PSI_stage_info stage_sorting_for_group= { 0, "Sorting for group", 0}; +PSI_stage_info stage_sorting_for_order= { 0, "Sorting for order", 0}; +PSI_stage_info stage_sorting_result= { 0, "Sorting result", 0}; +PSI_stage_info stage_statistics= { 0, "statistics", 0}; +PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0 }; +PSI_stage_info stage_storing_result_in_query_cache= { 0, "storing result in query cache", 0}; +PSI_stage_info stage_storing_row_into_queue= { 0, "storing row into queue", 0}; +PSI_stage_info stage_system_lock= { 0, "System lock", 0}; +PSI_stage_info stage_table_lock= { 0, "Table lock", 0}; +PSI_stage_info stage_filling_schema_table= { 0, "Filling schema table", 0}; +PSI_stage_info stage_update= { 0, "update", 0}; +PSI_stage_info stage_updating= { 0, "updating", 0}; +PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0}; +PSI_stage_info stage_updating_reference_tables= { 0, "updating reference tables", 0}; +PSI_stage_info stage_upgrading_lock= { 0, "upgrading lock", 0}; +PSI_stage_info stage_user_lock= { 0, "User lock", 0}; +PSI_stage_info stage_user_sleep= { 0, "User sleep", 0}; +PSI_stage_info stage_verifying_table= { 0, "verifying table", 0}; +PSI_stage_info stage_waiting_for_delay_list= { 0, "waiting for delay_list", 0}; +PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log= { 0, "waiting for GTID to be written to binary log", 0}; +PSI_stage_info stage_waiting_for_handler_insert= { 0, "waiting for handler insert", 0}; +PSI_stage_info stage_waiting_for_handler_lock= { 0, "waiting for handler lock", 0}; +PSI_stage_info stage_waiting_for_handler_open= { 0, "waiting for handler open", 0}; +PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0}; +PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0}; +PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0}; +PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0}; +PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0}; +PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0}; +PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0}; +PSI_stage_info stage_waiting_for_query_cache_lock= { 0, "Waiting for query cache lock", 0}; +PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0}; +PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0}; +PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0}; +PSI_stage_info stage_waiting_to_get_readlock= { 0, "Waiting to get readlock", 0}; +PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0}; +PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0}; +PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0}; +PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0}; +PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0}; +PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0}; +PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0}; +PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0}; +PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0}; +PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to commit", 0}; +PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0}; +PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0}; +PSI_stage_info stage_waiting_for_workers_idle= { 0, "Waiting for worker threads to be idle", 0}; +PSI_stage_info stage_waiting_for_ftwrl= { 0, "Waiting due to global read lock", 0}; +PSI_stage_info stage_waiting_for_ftwrl_threads_to_pause= { 0, "Waiting for worker threads to pause for global read lock", 0}; +PSI_stage_info stage_waiting_for_rpl_thread_pool= { 0, "Waiting while replication worker thread pool is busy", 0}; +PSI_stage_info stage_master_gtid_wait_primary= { 0, "Waiting in MASTER_GTID_WAIT() (primary waiter)", 0}; +PSI_stage_info stage_master_gtid_wait= { 0, "Waiting in MASTER_GTID_WAIT()", 0}; +PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process GTID received on multiple master connections", 0}; + +#ifdef HAVE_PSI_INTERFACE + +PSI_stage_info *all_server_stages[]= +{ + & stage_after_create, + & stage_after_opening_tables, + & stage_after_table_lock, + & stage_allocating_local_table, + & stage_alter_inplace, + & stage_alter_inplace_commit, + & stage_alter_inplace_prepare, + & stage_binlog_processing_checkpoint_notify, + & stage_binlog_stopping_background_thread, + & stage_binlog_waiting_background_tasks, + & stage_changing_master, + & stage_checking_master_version, + & stage_checking_permissions, + & stage_checking_privileges_on_cached_query, + & stage_checking_query_cache_for_query, + & stage_cleaning_up, + & stage_closing_tables, + & stage_connecting_to_master, + & stage_converting_heap_to_myisam, + & stage_copy_to_tmp_table, + & stage_copying_to_group_table, + & stage_copying_to_tmp_table, + & stage_creating_delayed_handler, + & stage_creating_sort_index, + & stage_creating_table, + & stage_creating_tmp_table, + & stage_deleting_from_main_table, + & stage_deleting_from_reference_tables, + & stage_discard_or_import_tablespace, + & stage_enabling_keys, + & stage_end, + & stage_executing, + & stage_execution_of_init_command, + & stage_explaining, + & stage_finding_key_cache, + & stage_finished_reading_one_binlog_switching_to_next_binlog, + & stage_flushing_relay_log_and_master_info_repository, + & stage_flushing_relay_log_info_file, + & stage_freeing_items, + & stage_fulltext_initialization, + & stage_got_handler_lock, + & stage_got_old_table, + & stage_init, + & stage_insert, + & stage_invalidating_query_cache_entries_table, + & stage_invalidating_query_cache_entries_table_list, + & stage_killing_slave, + & stage_logging_slow_query, + & stage_making_temp_file_append_before_load_data, + & stage_making_temp_file_create_before_load_data, + & stage_manage_keys, + & stage_master_has_sent_all_binlog_to_slave, + & stage_opening_tables, + & stage_optimizing, + & stage_preparing, + & stage_purging_old_relay_logs, + & stage_query_end, + & stage_queueing_master_event_to_the_relay_log, + & stage_reading_event_from_the_relay_log, + & stage_recreating_table, + & stage_registering_slave_on_master, + & stage_removing_duplicates, + & stage_removing_tmp_table, + & stage_rename, + & stage_rename_result_table, + & stage_requesting_binlog_dump, + & stage_reschedule, + & stage_searching_rows_for_update, + & stage_sending_binlog_event_to_slave, + & stage_sending_cached_result_to_client, + & stage_sending_data, + & stage_setup, + & stage_show_explain, + & stage_slave_has_read_all_relay_log, + & stage_slave_waiting_event_from_coordinator, + & stage_slave_waiting_worker_queue, + & stage_slave_waiting_worker_to_free_events, + & stage_slave_waiting_worker_to_release_partition, + & stage_slave_waiting_workers_to_exit, + & stage_sorting, + & stage_sorting_for_group, + & stage_sorting_for_order, + & stage_sorting_result, + & stage_sql_thd_waiting_until_delay, + & stage_statistics, + & stage_storing_result_in_query_cache, + & stage_storing_row_into_queue, + & stage_system_lock, + & stage_table_lock, + & stage_filling_schema_table, + & stage_update, + & stage_updating, + & stage_updating_main_table, + & stage_updating_reference_tables, + & stage_upgrading_lock, + & stage_user_lock, + & stage_user_sleep, + & stage_verifying_table, + & stage_waiting_for_delay_list, + & stage_waiting_for_gtid_to_be_written_to_binary_log, + & stage_waiting_for_handler_insert, + & stage_waiting_for_handler_lock, + & stage_waiting_for_handler_open, + & stage_waiting_for_insert, + & stage_waiting_for_master_to_send_event, + & stage_waiting_for_master_update, + & stage_waiting_for_prior_transaction_to_commit, + & stage_waiting_for_prior_transaction_to_start_commit, + & stage_waiting_for_query_cache_lock, + & stage_waiting_for_relay_log_space, + & stage_waiting_for_room_in_worker_thread, + & stage_waiting_for_slave_mutex_on_exit, + & stage_waiting_for_slave_thread_to_start, + & stage_waiting_for_table_flush, + & stage_waiting_for_the_next_event_in_relay_log, + & stage_waiting_for_the_slave_thread_to_advance_position, + & stage_waiting_for_work_from_sql_thread, + & stage_waiting_to_finalize_termination, + & stage_waiting_to_get_readlock, + & stage_master_gtid_wait_primary, + & stage_master_gtid_wait, + & stage_gtid_wait_other_connection +}; -/***************************************************************************** - Instantiate variables for missing storage engines - This section should go away soon -*****************************************************************************/ +PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection; -/***************************************************************************** - Instantiate templates -*****************************************************************************/ +static PSI_socket_info all_server_sockets[]= +{ + { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_GLOBAL}, + { &key_socket_unix, "server_unix_socket", PSI_FLAG_GLOBAL}, + { &key_socket_client_connection, "client_connection", 0} +}; -#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>; +/** + Initialise all the performance schema instrumentation points + used by the server. +*/ +void init_server_psi_keys(void) +{ + const char* category= "sql"; + int count; + + count= array_elements(all_server_mutexes); + mysql_mutex_register(category, all_server_mutexes, count); + + count= array_elements(all_server_rwlocks); + mysql_rwlock_register(category, all_server_rwlocks, count); + + count= array_elements(all_server_conds); + mysql_cond_register(category, all_server_conds, count); + + count= array_elements(all_server_threads); + mysql_thread_register(category, all_server_threads, count); + + count= array_elements(all_server_files); + mysql_file_register(category, all_server_files, count); + + count= array_elements(all_server_stages); + mysql_stage_register(category, all_server_stages, count); + + count= array_elements(all_server_sockets); + mysql_socket_register(category, all_server_sockets, count); + +#ifdef HAVE_PSI_STATEMENT_INTERFACE + init_sql_statement_info(); + count= array_elements(sql_statement_info); + mysql_statement_register(category, sql_statement_info, count); + + category= "com"; + init_com_statement_info(); + + /* + Register [0 .. COM_QUERY - 1] as "statement/com/..." + */ + count= (int) COM_QUERY; + mysql_statement_register(category, com_statement_info, count); + + /* + Register [COM_QUERY + 1 .. COM_END] as "statement/com/..." + */ + count= (int) COM_END - (int) COM_QUERY; + mysql_statement_register(category, & com_statement_info[(int) COM_QUERY + 1], count); + + category= "abstract"; + /* + Register [COM_QUERY] as "statement/abstract/com_query" + */ + mysql_statement_register(category, & com_statement_info[(int) COM_QUERY], 1); + + /* + When a new packet is received, + it is instrumented as "statement/abstract/new_packet". + Based on the packet type found, it later mutates to the + proper narrow type, for example + "statement/abstract/query" or "statement/com/ping". + In cases of "statement/abstract/query", SQL queries are given to + the parser, which mutates the statement type to an even more + narrow classification, for example "statement/sql/select". + */ + stmt_info_new_packet.m_key= 0; + stmt_info_new_packet.m_name= "new_packet"; + stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE; + mysql_statement_register(category, &stmt_info_new_packet, 1); + + /* + Statements processed from the relay log are initially instrumented as + "statement/abstract/relay_log". The parser will mutate the statement type to + a more specific classification, for example "statement/sql/insert". + */ + stmt_info_rpl.m_key= 0; + stmt_info_rpl.m_name= "relay_log"; + stmt_info_rpl.m_flags= PSI_FLAG_MUTABLE; + mysql_statement_register(category, &stmt_info_rpl, 1); #endif +} +#endif /* HAVE_PSI_INTERFACE */ |