diff options
Diffstat (limited to 'sql')
52 files changed, 1145 insertions, 869 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 4097d7fe6e1..3ef1f22e2b8 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1520,6 +1520,8 @@ static void debug_sync(THD *thd, const char *sync_point_name, size_t name_len) { if (!thd) thd= current_thd; + if (!thd) + return; st_debug_sync_control *ds_control= thd->debug_sync_control; st_debug_sync_action *action; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 0eb65cff91e..7da6d4f83b6 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -222,7 +222,8 @@ mysql_event_fill_row(THD *thd, Safety: this can only happen if someone started the server and then altered mysql.event. */ - my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, MYF(0), table->alias.c_ptr(), + my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2, MYF(0), + table->s->db.str, table->alias.c_ptr(), (int) ET_FIELD_COUNT, table->s->fields); DBUG_RETURN(TRUE); } @@ -426,7 +427,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, key_info->key_part[0].field != event_table->field[ET_FIELD_DB]) { /* Corrupted table: no index or index on a wrong column */ - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event"); + my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event"); ret= 1; goto end; } @@ -1084,7 +1085,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, if ((ret= find_named_event(dbname, name, event_table.table))) my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str); else if ((ret= etn->load_from_row(thd, event_table.table))) - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event"); + my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event"); close_system_tables(thd, &open_tables_backup); } diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 40fddff094c..0324e05fb27 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -10,8 +10,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #include "sql_priv.h" #include "unireg.h" @@ -559,9 +559,6 @@ Event_queue::dbug_dump_queue(my_time_t when) #endif } -static const char *queue_empty_msg= "Waiting on empty queue"; -static const char *queue_wait_msg= "Waiting for next activation"; - /* Checks whether the top of the queue is elligible for execution and returns an Event_job_data instance in case it should be executed. @@ -608,7 +605,7 @@ Event_queue::get_top_for_execution_if_time(THD *thd, mysql_audit_release(thd); /* Wait on condition until signaled. Release LOCK_queue while waiting. */ - cond_wait(thd, NULL, queue_empty_msg, SCHED_FUNC, __LINE__); + cond_wait(thd, NULL, & stage_waiting_on_empty_queue, SCHED_FUNC, __FILE__, __LINE__); continue; } @@ -629,7 +626,8 @@ Event_queue::get_top_for_execution_if_time(THD *thd, /* Release any held audit resources before waiting */ mysql_audit_release(thd); - cond_wait(thd, &top_time, queue_wait_msg, SCHED_FUNC, __LINE__); + cond_wait(thd, &top_time, &stage_waiting_for_next_activation, SCHED_FUNC, __FILE__, __LINE__); + continue; } @@ -759,16 +757,16 @@ Event_queue::unlock_data(const char *func, uint line) */ void -Event_queue::cond_wait(THD *thd, struct timespec *abstime, const char* msg, - const char *func, uint line) +Event_queue::cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, + const char *src_func, const char *src_file, uint src_line) { DBUG_ENTER("Event_queue::cond_wait"); waiting_on_cond= TRUE; - mutex_last_unlocked_at_line= line; + mutex_last_unlocked_at_line= src_line; mutex_queue_data_locked= FALSE; - mutex_last_unlocked_in_func= func; + mutex_last_unlocked_in_func= src_func; - thd->enter_cond(&COND_queue_state, &LOCK_event_queue, msg); + thd->enter_cond(&COND_queue_state, &LOCK_event_queue, stage, NULL, src_func, src_file, src_line); if (!thd->killed) { @@ -779,8 +777,8 @@ Event_queue::cond_wait(THD *thd, struct timespec *abstime, const char* msg, mysql_cond_timedwait(&COND_queue_state, &LOCK_event_queue, abstime); } - mutex_last_locked_in_func= func; - mutex_last_locked_at_line= line; + mutex_last_locked_in_func= src_func; + mutex_last_locked_at_line= src_line; mutex_queue_data_locked= TRUE; waiting_on_cond= FALSE; @@ -788,8 +786,8 @@ Event_queue::cond_wait(THD *thd, struct timespec *abstime, const char* msg, This will free the lock so we need to relock. Not the best thing to do but we need to obey cond_wait() */ - thd->exit_cond(""); - lock_data(func, line); + thd->exit_cond(NULL, src_func, src_file, src_line); + lock_data(src_func, src_line); DBUG_VOID_RETURN; } diff --git a/sql/event_queue.h b/sql/event_queue.h index affa306b259..fdd5937ee17 100644 --- a/sql/event_queue.h +++ b/sql/event_queue.h @@ -12,8 +12,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /** @@ -94,8 +94,8 @@ private: unlock_data(const char *func, uint line); void - cond_wait(THD *thd, struct timespec *abstime, const char* msg, - const char *func, uint line); + cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, + const char *src_func, const char *src_file, uint src_line); void find_n_remove_event(LEX_STRING db, LEX_STRING name); diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index fae703e23c4..58aedcc45e2 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. 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 @@ -38,8 +38,8 @@ #define LOCK_DATA() lock_data(SCHED_FUNC, __LINE__) #define UNLOCK_DATA() unlock_data(SCHED_FUNC, __LINE__) -#define COND_STATE_WAIT(mythd, abstime, msg) \ - cond_wait(mythd, abstime, msg, SCHED_FUNC, __LINE__) +#define COND_STATE_WAIT(mythd, abstime, stage) \ + cond_wait(mythd, abstime, stage, SCHED_FUNC, __FILE__, __LINE__) extern pthread_attr_t connection_attrib; @@ -405,7 +405,7 @@ Event_scheduler::start() } pre_init_event_thread(new_thd); new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER; - new_thd->command= COM_DAEMON; + new_thd->set_command(COM_DAEMON); /* We should run the event scheduler thread under the super-user privileges. @@ -632,7 +632,7 @@ Event_scheduler::stop() { /* Synchronously wait until the scheduler stops. */ while (state != INITIALIZED) - COND_STATE_WAIT(thd, NULL, "Waiting for the scheduler to stop"); + COND_STATE_WAIT(thd, NULL, &stage_waiting_for_scheduler_to_stop); goto end; } @@ -674,7 +674,7 @@ Event_scheduler::stop() */ struct timespec top_time; set_timespec(top_time, 2); - COND_STATE_WAIT(thd, &top_time, "Waiting scheduler to stop"); + COND_STATE_WAIT(thd, NULL, &stage_waiting_for_scheduler_to_stop); } while (state == STOPPING); DBUG_PRINT("info", ("Scheduler thread has cleaned up. Set state to INIT")); sql_print_information("Event Scheduler: Stopped"); @@ -768,16 +768,17 @@ Event_scheduler::unlock_data(const char *func, uint line) */ void -Event_scheduler::cond_wait(THD *thd, struct timespec *abstime, const char* msg, - const char *func, uint line) +Event_scheduler::cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, + const char *src_func, const char *src_file, uint src_line) { DBUG_ENTER("Event_scheduler::cond_wait"); waiting_on_cond= TRUE; - mutex_last_unlocked_at_line= line; + mutex_last_unlocked_at_line= src_line; mutex_scheduler_data_locked= FALSE; - mutex_last_unlocked_in_func= func; + mutex_last_unlocked_in_func= src_func; if (thd) - thd->enter_cond(&COND_state, &LOCK_scheduler_state, msg); + thd->enter_cond(&COND_state, &LOCK_scheduler_state, stage, + NULL, src_func, src_file, src_line); DBUG_PRINT("info", ("mysql_cond_%swait", abstime? "timed":"")); if (!abstime) @@ -790,11 +791,11 @@ Event_scheduler::cond_wait(THD *thd, struct timespec *abstime, const char* msg, This will free the lock so we need to relock. Not the best thing to do but we need to obey cond_wait() */ - thd->exit_cond(""); + thd->exit_cond(NULL, src_func, src_file, src_line); LOCK_DATA(); } - mutex_last_locked_in_func= func; - mutex_last_locked_at_line= line; + mutex_last_locked_in_func= src_func; + mutex_last_locked_at_line= src_line; mutex_scheduler_data_locked= TRUE; waiting_on_cond= FALSE; DBUG_VOID_RETURN; diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index aca4b74dd95..0b160ff49d5 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -12,8 +12,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /** @addtogroup Event_Scheduler @@ -114,8 +114,8 @@ private: unlock_data(const char *func, uint line); void - cond_wait(THD *thd, struct timespec *abstime, const char* msg, - const char *func, uint line); + cond_wait(THD *thd, struct timespec *abstime, const PSI_stage_info *stage, + const char *src_func, const char *src_file, uint src_line); mysql_mutex_t LOCK_scheduler_state; diff --git a/sql/events.cc b/sql/events.cc index d403e38d784..0a14038bc27 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -947,23 +947,37 @@ static PSI_thread_info all_events_threads[]= { &key_thread_event_scheduler, "event_scheduler", PSI_FLAG_GLOBAL}, { &key_thread_event_worker, "event_worker", 0} }; +#endif /* HAVE_PSI_INTERFACE */ + +PSI_stage_info stage_waiting_on_empty_queue= { 0, "Waiting on empty queue", 0}; +PSI_stage_info stage_waiting_for_next_activation= { 0, "Waiting for next activation", 0}; +PSI_stage_info stage_waiting_for_scheduler_to_stop= { 0, "Waiting for the scheduler to stop", 0}; + +#ifdef HAVE_PSI_INTERFACE +PSI_stage_info *all_events_stages[]= +{ + & stage_waiting_on_empty_queue, + & stage_waiting_for_next_activation, + & stage_waiting_for_scheduler_to_stop +}; static void init_events_psi_keys(void) { const char* category= "sql"; int count; - if (PSI_server == NULL) - return; - count= array_elements(all_events_mutexes); - PSI_server->register_mutex(category, all_events_mutexes, count); + mysql_mutex_register(category, all_events_mutexes, count); count= array_elements(all_events_conds); - PSI_server->register_cond(category, all_events_conds, count); + mysql_cond_register(category, all_events_conds, count); count= array_elements(all_events_threads); - PSI_server->register_thread(category, all_events_threads, count); + mysql_thread_register(category, all_events_threads, count); + + count= array_elements(all_events_stages); + mysql_stage_register(category, all_events_stages, count); + } #endif /* HAVE_PSI_INTERFACE */ diff --git a/sql/events.h b/sql/events.h index a94fbc17135..4720c301052 100644 --- a/sql/events.h +++ b/sql/events.h @@ -31,6 +31,11 @@ extern PSI_cond_key key_event_scheduler_COND_state; extern PSI_thread_key key_thread_event_scheduler, key_thread_event_worker; #endif /* HAVE_PSI_INTERFACE */ +/* Always defined, for SHOW PROCESSLIST. */ +extern PSI_stage_info stage_waiting_on_empty_queue; +extern PSI_stage_info stage_waiting_for_next_activation; +extern PSI_stage_info stage_waiting_for_scheduler_to_stop; + #include "sql_string.h" /* LEX_STRING */ #include "my_time.h" /* interval_type */ diff --git a/sql/filesort.cc b/sql/filesort.cc index 03379f2738a..7ee4dc52557 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -180,9 +180,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, param.max_rows= max_rows; if (select && select->quick) - status_var_increment(thd->status_var.filesort_range_count); + thd->inc_status_sort_range(); else - status_var_increment(thd->status_var.filesort_scan_count); + thd->inc_status_sort_scan(); thd->query_plan_flags|= QPLAN_FILESORT; // If number of rows is not known, use as much of sort buffer as possible. @@ -346,8 +346,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } } else - statistic_add(thd->status_var.filesort_rows, - (ulong) num_rows, &LOCK_status); + thd->inc_status_sort_rows(num_rows); *examined_rows= param.examined_rows; #ifdef SKIP_DBUG_IN_FILESORT DBUG_POP(); /* Ok to DBUG */ @@ -1218,6 +1217,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb, int flag) { + THD *thd= current_thd; int error; uint rec_length,res_length,offset; size_t sort_length; @@ -1233,11 +1233,11 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, uchar *src; killed_state not_killable; uchar *unique_buff= param->unique_buff; - volatile killed_state *killed= ¤t_thd->killed; + volatile killed_state *killed= &thd->killed; DBUG_ENTER("merge_buffers"); - status_var_increment(current_thd->status_var.filesort_merge_passes); - current_thd->query_plan_fsort_passes++; + thd->inc_status_sort_merge_passes(); + thd->query_plan_fsort_passes++; if (param->not_killable) { killed= ¬_killable; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5118818fa54..0b46ca4123c 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2913,6 +2913,35 @@ err_alloc: } +void ha_partition::unbind_psi() +{ + uint i; + + DBUG_ENTER("ha_partition::unbind_psi"); + handler::unbind_psi(); + for (i= 0; i < m_tot_parts; i++) + { + DBUG_ASSERT(m_file[i] != NULL); + m_file[i]->unbind_psi(); + } + DBUG_VOID_RETURN; +} + +void ha_partition::rebind_psi() +{ + uint i; + + DBUG_ENTER("ha_partition::rebind_psi"); + handler::rebind_psi(); + for (i= 0; i < m_tot_parts; i++) + { + DBUG_ASSERT(m_file[i] != NULL); + m_file[i]->rebind_psi(); + } + DBUG_VOID_RETURN; +} + + /** Clone the open and locked partitioning handler. diff --git a/sql/ha_partition.h b/sql/ha_partition.h index aa9179f9f69..b6b0e2a015d 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -306,6 +306,8 @@ public: If the object was opened it will also be closed before being deleted. */ virtual int open(const char *name, int mode, uint test_if_locked); + virtual void unbind_psi(); + virtual void rebind_psi(); virtual int close(void); /* diff --git a/sql/handler.cc b/sql/handler.cc index 7f1d4038af4..ae9345d7673 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009-2011 Monty Program Ab + Copyright (c) 2009, 2012, Monty Program Ab. 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 @@ -20,10 +20,6 @@ Handler-calling-functions */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - #include "sql_priv.h" #include "unireg.h" #include "rpl_handler.h" @@ -42,6 +38,7 @@ #include "transaction.h" #include "myisam.h" #include "probes_mysql.h" +#include <mysql/psi/mysql_table.h> #include "debug_sync.h" // DEBUG_SYNC #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -363,9 +360,9 @@ int ha_init_errors(void) SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS)); SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG)); SETMSG(HA_ERR_INDEX_CORRUPT, ER_DEFAULT(ER_INDEX_CORRUPT)); + SETMSG(HA_FTS_INVALID_DOCID, "Invalid InnoDB FTS Doc ID"); SETMSG(HA_ERR_TABLE_IN_FK_CHECK, ER_DEFAULT(ER_TABLE_IN_FK_CHECK)); SETMSG(HA_ERR_DISK_FULL, ER_DEFAULT(ER_DISK_FULL)); - SETMSG(HA_FTS_INVALID_DOCID, "Invalid InnoDB FTS Doc ID"); /* Register the error messages for use with my_error(). */ return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -505,10 +502,6 @@ int ha_initialize_handlerton(st_plugin_int *plugin) "Assigning value %d.", plugin->plugin->name, idx); hton->db_type= (enum legacy_db_type) idx; } - installed_htons[hton->db_type]= hton; - tmp= hton->savepoint_offset; - hton->savepoint_offset= savepoint_alloc_size; - savepoint_alloc_size+= tmp; /* In case a plugin is uninstalled and re-installed later, it should @@ -721,7 +714,7 @@ void ha_close_connection(THD* thd) end. Such nested transaction was internally referred to as a "statement transaction" and gave birth to the term. - <Historical note ends> + (Historical note ends) Since then a statement transaction is started for each statement that accesses transactional tables or uses the binary log. If @@ -2343,6 +2336,150 @@ int handler::ha_close(void) DBUG_RETURN(close()); } +int handler::ha_rnd_next(uchar *buf) +{ + int result; + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0, + { result= rnd_next(buf); }) + if (!result) + { + update_rows_read(); + increment_statistics(&SSV::ha_read_rnd_next_count); + } + else if (result == HA_ERR_RECORD_DELETED) + increment_statistics(&SSV::ha_read_rnd_deleted_count); + else + increment_statistics(&SSV::ha_read_rnd_next_count); + + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_rnd_pos(uchar *buf, uchar *pos) +{ + int result; + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0, + { result= rnd_pos(buf, pos); }) + increment_statistics(&SSV::ha_read_rnd_count); + if (!result) + update_rows_read(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_read_map(uchar *buf, const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_read_map(buf, key, keypart_map, find_flag); }) + increment_statistics(&SSV::ha_read_key_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +/* + @note: Other index lookup/navigation functions require prior + handler->index_init() call. This function is different, it requires + that the scan is not initialized, and accepts "uint index" as an argument. +*/ + +int handler::ha_index_read_idx_map(uchar *buf, uint index, const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + int result; + DBUG_ASSERT(inited==NONE); + DBUG_ASSERT(end_range == NULL); + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, index, 0, + { result= index_read_idx_map(buf, index, key, keypart_map, find_flag); }) + increment_statistics(&SSV::ha_read_key_count); + if (!result) + { + update_rows_read(); + index_rows_read[index]++; + } + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_next(uchar * buf) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_next(buf); }) + increment_statistics(&SSV::ha_read_next_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_prev(uchar * buf) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_prev(buf); }) + increment_statistics(&SSV::ha_read_prev_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_first(uchar * buf) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_first(buf); }) + increment_statistics(&SSV::ha_read_first_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_last(uchar * buf) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_last(buf); }) + increment_statistics(&SSV::ha_read_last_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + +int handler::ha_index_next_same(uchar *buf, const uchar *key, uint keylen) +{ + int result; + DBUG_ASSERT(inited==INDEX); + + MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, + { result= index_next_same(buf, key, keylen); }) + increment_statistics(&SSV::ha_read_next_count); + if (!result) + update_index_statistics(); + table->status=result ? STATUS_NOT_FOUND: 0; + return result; +} + /* Initialize handler for random reading, with error handling */ int handler::ha_rnd_init_with_error(bool scan) @@ -2931,44 +3068,28 @@ void handler::print_error(int error, myf errflag) } case HA_ERR_FOREIGN_DUPLICATE_KEY: { - uint key_nr= get_dup_key(error); - if ((int) key_nr >= 0) + char rec_buf[MAX_KEY_LENGTH]; + String rec(rec_buf, sizeof(rec_buf), system_charset_info); + /* Table is opened and defined at this point */ + key_unpack(&rec, table, 0 /* just print the subset of fields that are + part of the first index, printing the whole + row from there is not easy */); + + char child_table_name[NAME_LEN + 1]; + char child_key_name[NAME_LEN + 1]; + if (get_foreign_dup_key(child_table_name, sizeof(child_table_name), + child_key_name, sizeof(child_key_name))) { - uint max_length; - /* Write the key in the error message */ - char key[MAX_KEY_LENGTH]; - String str(key,sizeof(key),system_charset_info); - /* Table is opened and defined at this point */ - - /* - Use primary_key instead of key_nr because key_nr is a key - number in the child FK table, not in our 'table'. See - Bug#12661768 UPDATE IGNORE CRASHES SERVER IF TABLE IS INNODB - AND IT IS PARENT FOR OTHER ONE This bug gets a better fix in - MySQL 5.6, but it is too risky to get that in 5.1 and 5.5 - (extending the handler interface and adding new error message - codes) - */ - if (table->s->primary_key < MAX_KEY) - key_unpack(&str,table,table->s->primary_key); - else - { - LEX_CUSTRING tmp= {USTRING_WITH_LEN("Unknown key value")}; - str.set((const char*) tmp.str, tmp.length, system_charset_info); - } - max_length= (MYSQL_ERRMSG_SIZE- - (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY))); - if (str.length() >= max_length) - { - str.length(max_length-4); - str.append(STRING_WITH_LEN("...")); + my_error(ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO, errflag, + table_share->table_name.str, rec.c_ptr_safe(), + child_table_name, child_key_name); } - my_error(ER_FOREIGN_DUPLICATE_KEY, errflag, table_share->table_name.str, - str.c_ptr_safe(), key_nr+1); - DBUG_VOID_RETURN; + else + { + my_error(ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO, errflag, + table_share->table_name.str, rec.c_ptr_safe()); } - textno= ER_DUP_KEY; - break; + DBUG_VOID_RETURN; } case HA_ERR_NULL_IN_SPATIAL: my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, errflag); diff --git a/sql/handler.h b/sql/handler.h index da57f1a19a4..3a6f0070567 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2015,6 +2015,29 @@ public: virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); + /** + Retrieves the names of the table and the key for which there was a + duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY. + + If any of the table or key name is not available this method will return + false and will not change any of child_table_name or child_key_name. + + @param child_table_name[out] Table name + @param child_table_name_len[in] Table name buffer size + @param child_key_name[out] Key name + @param child_key_name_len[in] Key name buffer size + + @retval true table and key names were available + and were written into the corresponding + out parameters. + @retval false table and key names were not available, + the out parameters were not touched. + */ + virtual bool get_foreign_dup_key(char *child_table_name, + uint child_table_name_len, + char *child_key_name, + uint child_key_name_len) + { DBUG_ASSERT(false); return(false); } void reset_statistics() { rows_read= rows_changed= rows_tmp_read= 0; @@ -2193,18 +2216,17 @@ protected: } public: - /* Similar functions like the above, but does statistics counting */ - inline int ha_index_read_map(uchar * buf, const uchar * key, - key_part_map keypart_map, - enum ha_rkey_function find_flag); - inline int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key, - key_part_map keypart_map, - enum ha_rkey_function find_flag); - inline int ha_index_next(uchar * buf); - inline int ha_index_prev(uchar * buf); - inline int ha_index_first(uchar * buf); - inline int ha_index_last(uchar * buf); - inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen); + int ha_index_read_map(uchar * buf, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); + int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); + int ha_index_next(uchar * buf); + int ha_index_prev(uchar * buf); + int ha_index_first(uchar * buf); + int ha_index_last(uchar * buf); + int ha_index_next_same(uchar *buf, const uchar *key, uint keylen); /* TODO: should we make for those functions non-virtual ha_func_name wrappers, too? @@ -2276,8 +2298,8 @@ public: /* Same as above, but with statistics */ inline int ha_ft_read(uchar *buf); - inline int ha_rnd_next(uchar *buf); - inline int ha_rnd_pos(uchar *buf, uchar *pos); + int ha_rnd_next(uchar *buf); + int ha_rnd_pos(uchar *buf, uchar *pos); inline int ha_rnd_pos_by_record(uchar *buf); inline int ha_read_first_row(uchar *buf, uint primary_key); @@ -2756,7 +2778,7 @@ private: */ virtual int open(const char *name, int mode, uint test_if_locked)=0; - /* Note: ha_index_read_idx_map() may buypass index_init() */ + /* Note: ha_index_read_idx_map() may bypass index_init() */ virtual int index_init(uint idx, bool sorted) { return 0; } virtual int index_end() { return 0; } /** diff --git a/sql/item_func.cc b/sql/item_func.cc index d65f13931e2..922d980074a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4038,7 +4038,7 @@ longlong Item_func_get_lock::val_int() Structure is now initialized. Try to get the lock. Set up control struct to allow others to abort locks. */ - thd_proc_info(thd, "User lock"); + THD_STAGE_INFO(thd, stage_user_lock); thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; @@ -4084,7 +4084,6 @@ longlong Item_func_get_lock::val_int() mysql_mutex_unlock(&LOCK_user_locks); mysql_mutex_lock(&thd->mysys_var->mutex); - thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; mysql_mutex_unlock(&thd->mysys_var->mutex); @@ -4270,7 +4269,7 @@ longlong Item_func_sleep::val_int() mysql_cond_init(key_item_func_sleep_cond, &cond, NULL); mysql_mutex_lock(&LOCK_user_locks); - thd_proc_info(thd, "User sleep"); + THD_STAGE_INFO(thd, stage_user_sleep); thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &cond; @@ -4284,7 +4283,6 @@ longlong Item_func_sleep::val_int() error= 0; } thd_wait_end(thd); - thd_proc_info(thd, 0); mysql_mutex_unlock(&LOCK_user_locks); mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; diff --git a/sql/lock.cc b/sql/lock.cc index 3a1a6d41ce3..bf53a925424 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -11,8 +11,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /** @@ -304,7 +304,7 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) DBUG_ENTER("mysql_lock_tables(sql_lock)"); - thd_proc_info(thd, "System lock"); + THD_STAGE_INFO(thd, stage_system_lock); if (sql_lock->table_count && lock_external(thd, sql_lock->table, sql_lock->table_count)) goto end; @@ -323,8 +323,6 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) (void) unlock_external(thd, sql_lock->table, sql_lock->table_count); end: - thd_proc_info(thd, 0); - if (thd->killed) { thd->send_kill_message(); @@ -759,6 +757,7 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) for ( ; locks_start != locks ; locks_start++) { (*locks_start)->debug_print_param= (void *) table; + (*locks_start)->m_psi= table->file->m_psi; (*locks_start)->lock->name= table->alias.c_ptr(); (*locks_start)->org_type= (*locks_start)->type; } diff --git a/sql/log.cc b/sql/log.cc index 801d945f3f0..527ea133eae 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -822,10 +822,10 @@ bool Log_to_csv_event_handler:: if (table->field[3]->store_time(&t)) goto err; /* rows_sent */ - if (table->field[4]->store((longlong) thd->sent_row_count, TRUE)) + if (table->field[4]->store((longlong) thd->get_sent_row_count(), TRUE)) goto err; /* rows_examined */ - if (table->field[5]->store((longlong) thd->examined_row_count, TRUE)) + if (table->field[5]->store((longlong) thd->get_examined_row_count(), TRUE)) goto err; /* fill database field */ @@ -1252,8 +1252,8 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, if (!query) { is_command= TRUE; - query= command_name[thd->command].str; - query_length= command_name[thd->command].length; + query= command_name[thd->get_command()].str; + query_length= command_name[thd->get_command()].length; } for (current_handler= slow_log_handler_list; *current_handler ;) @@ -2067,9 +2067,7 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd) static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("binlog_savepoint_set"); - - binlog_trans_log_savepos(thd, (my_off_t*) sv); - /* Write it to the binary log */ + int error= 1; String log_query; if (log_query.append(STRING_WITH_LEN("SAVEPOINT ")) || @@ -2078,9 +2076,25 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) log_query.append("`")) DBUG_RETURN(1); int errcode= query_error_code(thd, thd->killed == NOT_KILLED); - Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), + Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(), TRUE, FALSE, TRUE, errcode); - DBUG_RETURN(mysql_bin_log.write(&qinfo)); + /* + We cannot record the position before writing the statement + because a rollback to a savepoint (.e.g. consider it "S") would + prevent the savepoint statement (i.e. "SAVEPOINT S") from being + written to the binary log despite the fact that the server could + still issue other rollback statements to the same savepoint (i.e. + "S"). + Given that the savepoint is valid until the server releases it, + ie, until the transaction commits or it is released explicitly, + we need to log it anyway so that we don't have "ROLLBACK TO S" + or "RELEASE S" without the preceding "SAVEPOINT S" in the binary + log. + */ + if (!(error= mysql_bin_log.write(&qinfo))) + binlog_trans_log_savepos(thd, (my_off_t*) sv); + + DBUG_RETURN(error); } static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) @@ -2771,8 +2785,8 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, (ulong) thd->thread_id, (thd->db ? thd->db : ""), ((thd->query_plan_flags & QPLAN_QC) ? "Yes" : "No"), query_time_buff, lock_time_buff, - (ulong) thd->sent_row_count, - (ulong) thd->examined_row_count) == (size_t) -1) + (ulong) thd->get_sent_row_count(), + (ulong) thd->get_examined_row_count()) == (size_t) -1) tmp_errno= errno; if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) && (thd->query_plan_flags & @@ -6253,15 +6267,14 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry) void MYSQL_BIN_LOG::wait_for_update_relay_log(THD* thd) { - const char *old_msg; + PSI_stage_info old_stage; DBUG_ENTER("wait_for_update_relay_log"); - old_msg= thd->enter_cond(&update_cond, &LOCK_log, - "Slave has read all relay log; " - "waiting for the slave I/O " - "thread to update it" ); + thd->ENTER_COND(&update_cond, &LOCK_log, + &stage_slave_has_read_all_relay_log, + &old_stage); mysql_cond_wait(&update_cond, &LOCK_log); - thd->exit_cond(old_msg); + thd->EXIT_COND(&old_stage); DBUG_VOID_RETURN; } diff --git a/sql/log_event.cc b/sql/log_event.cc index b6c1d15a0d6..f884b2996f0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6975,16 +6975,15 @@ void Create_file_log_event::pack_info(Protocol *protocol) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Create_file_log_event::do_apply_event(Relay_log_info const *rli) { - char proc_info[17+FN_REFLEN+10], *fname_buf; + char fname_buf[FN_REFLEN]; char *ext; int fd = -1; IO_CACHE file; int error = 1; + THD_STAGE_INFO(thd, stage_making_temp_file_create_before_load_data); bzero((char*)&file, sizeof(file)); - fname_buf= strmov(proc_info, "Making temp file "); ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info"); - thd_proc_info(thd, proc_info); /* old copy may exist already */ mysql_file_delete(key_file_log_event_info, fname_buf, MYF(0)); if ((fd= mysql_file_create(key_file_log_event_info, @@ -7041,7 +7040,6 @@ err: end_io_cache(&file); if (fd >= 0) mysql_file_close(fd, MYF(0)); - thd_proc_info(thd, 0); return error != 0; } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -7155,14 +7153,13 @@ int Append_block_log_event::get_create_or_append() const int Append_block_log_event::do_apply_event(Relay_log_info const *rli) { - char proc_info[17+FN_REFLEN+10], *fname= proc_info+17; + char fname[FN_REFLEN]; int fd; int error = 1; DBUG_ENTER("Append_block_log_event::do_apply_event"); - fname= strmov(proc_info, "Making temp file "); + THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data); slave_load_file_stem(fname, file_id, server_id, ".data"); - thd_proc_info(thd, proc_info); if (get_create_or_append()) { /* @@ -7212,7 +7209,6 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) err: if (fd >= 0) mysql_file_close(fd, MYF(0)); - thd_proc_info(thd, 0); DBUG_RETURN(error); } #endif diff --git a/sql/mdl.cc b/sql/mdl.cc index ca552a540b9..0e30e44c19a 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -10,16 +10,18 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #include "mdl.h" +#include "sql_class.h" #include "debug_sync.h" #include <hash.h> #include <mysqld_error.h> #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> +#include <mysql/psi/mysql_stage.h> #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; @@ -53,20 +55,18 @@ static PSI_cond_info all_mdl_conds[]= */ static void init_mdl_psi_keys(void) { - const char *category= "sql"; int count; - if (PSI_server == NULL) - return; - count= array_elements(all_mdl_mutexes); - PSI_server->register_mutex(category, all_mdl_mutexes, count); + mysql_mutex_register("sql", all_mdl_mutexes, count); count= array_elements(all_mdl_rwlocks); - PSI_server->register_rwlock(category, all_mdl_rwlocks, count); + mysql_rwlock_register("sql", all_mdl_rwlocks, count); count= array_elements(all_mdl_conds); - PSI_server->register_cond(category, all_mdl_conds, count); + mysql_cond_register("sql", all_mdl_conds, count); + + MDL_key::init_psi_keys(); } #endif /* HAVE_PSI_INTERFACE */ @@ -76,18 +76,35 @@ static void init_mdl_psi_keys(void) belonging to certain namespace. */ -const char *MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]= +PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]= { - "Waiting for global read lock", - "Waiting for schema metadata lock", - "Waiting for table metadata lock", - "Waiting for stored function metadata lock", - "Waiting for stored procedure metadata lock", - "Waiting for trigger metadata lock", - "Waiting for event metadata lock", - "Waiting for commit lock" + {0, "Waiting for global read lock", 0}, + {0, "Waiting for schema metadata lock", 0}, + {0, "Waiting for table metadata lock", 0}, + {0, "Waiting for stored function metadata lock", 0}, + {0, "Waiting for stored procedure metadata lock", 0}, + {0, "Waiting for trigger metadata lock", 0}, + {0, "Waiting for event metadata lock", 0}, + {0, "Waiting for commit lock", 0} }; +#ifdef HAVE_PSI_INTERFACE +void MDL_key::init_psi_keys() +{ + int i; + int count; + PSI_stage_info *info __attribute__((unused)); + + count= array_elements(MDL_key::m_namespace_to_wait_state_name); + for (i= 0; i<count; i++) + { + /* mysql_stage_register wants an array of pointers, registering 1 by 1. */ + info= & MDL_key::m_namespace_to_wait_state_name[i]; + mysql_stage_register("sql", &info, 1); + } +} +#endif + static bool mdl_initialized= 0; @@ -1140,18 +1157,18 @@ void MDL_wait::reset_status() MDL_wait::enum_wait_status MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, - bool set_status_on_timeout, const char *wait_state_name) + bool set_status_on_timeout, + const PSI_stage_info *wait_state_name) { - const char *old_msg; + PSI_stage_info old_stage; enum_wait_status result; int wait_result= 0; DBUG_ENTER("MDL_wait::timed_wait"); mysql_mutex_lock(&m_LOCK_wait_status); - old_msg= thd_enter_cond(thd, &m_COND_wait_status, &m_LOCK_wait_status, - wait_state_name); - + THD_ENTER_COND(thd, &m_COND_wait_status, &m_LOCK_wait_status, + wait_state_name, & old_stage); thd_wait_begin(thd, THD_WAIT_META_DATA_LOCK); while (!m_wait_status && !thd_killed(thd) && wait_result != ETIMEDOUT && wait_result != ETIME) @@ -1182,7 +1199,7 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, } result= m_wait_status; - thd_exit_cond(thd, old_msg); + thd->EXIT_COND(& old_stage); DBUG_RETURN(result); } diff --git a/sql/mdl.h b/sql/mdl.h index d50de7d14c3..f816d160f7b 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -37,6 +37,24 @@ class MDL_lock; class MDL_ticket; /** + @def ENTER_COND(C, M, S, O) + Start a wait on a condition. + @param C the condition to wait on + @param M the associated mutex + @param S the new stage to enter + @param O the previous stage + @sa EXIT_COND(). +*/ +#define ENTER_COND(C, M, S, O) enter_cond(C, M, S, O, __func__, __FILE__, __LINE__) + +/** + @def EXIT_COND(S) + End a wait on a condition + @param S the new stage to enter +*/ +#define EXIT_COND(S) exit_cond(S, __func__, __FILE__, __LINE__) + +/** Type of metadata lock request. @sa Comments for MDL_object_lock::can_grant_lock() and @@ -189,6 +207,10 @@ enum enum_mdl_duration { class MDL_key { public: +#ifdef HAVE_PSI_INTERFACE + static void init_psi_keys(); +#endif + /** Object namespaces. Sic: when adding a new member to this enum make sure to @@ -284,16 +306,16 @@ public: Get thread state name to be used in case when we have to wait on resource identified by key. */ - const char * get_wait_state_name() const + const PSI_stage_info * get_wait_state_name() const { - return m_namespace_to_wait_state_name[(int)mdl_namespace()]; + return & m_namespace_to_wait_state_name[(int)mdl_namespace()]; } private: uint16 m_length; uint16 m_db_name_length; char m_ptr[MAX_MDLKEY_LENGTH]; - static const char * m_namespace_to_wait_state_name[NAMESPACE_END]; + static PSI_stage_info m_namespace_to_wait_state_name[NAMESPACE_END]; private: MDL_key(const MDL_key &); /* not implemented */ MDL_key &operator=(const MDL_key &); /* not implemented */ @@ -592,8 +614,10 @@ public: bool set_status(enum_wait_status result_arg); enum_wait_status get_status(); void reset_status(); - enum_wait_status timed_wait(THD *thd, struct timespec *abs_timeout, - bool signal_timeout, const char *wait_state_name); + enum_wait_status timed_wait(THD *thd, + struct timespec *abs_timeout, + bool signal_timeout, + const PSI_stage_info *wait_state_name); private: /** Condvar which is used for waiting until this context's pending @@ -837,16 +861,8 @@ private: void mdl_init(); void mdl_destroy(); - -/* - Functions in the server's kernel used by metadata locking subsystem. -*/ - extern bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, bool needs_thr_lock_abort); -extern "C" const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, - mysql_mutex_t *mutex, const char *msg); -extern "C" void thd_exit_cond(MYSQL_THD thd, const char *old_msg); #ifndef DBUG_OFF extern mysql_mutex_t LOCK_open; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index aa31966256d..b259565d6e0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -870,7 +870,6 @@ static PSI_cond_info all_server_conds[]= { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 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}, @@ -1941,7 +1940,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); @@ -2343,6 +2341,9 @@ static void network_init(void) 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); @@ -4002,7 +4003,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); @@ -4233,7 +4233,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 /* @@ -4483,7 +4483,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"); @@ -5577,6 +5577,7 @@ void handle_connections_sockets() 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) \ + mysql_socket_set_thread_owner(X); \ pfs_fds[socket_count]= (X); \ fds[socket_count].fd= mysql_socket_getfd(X); \ fds[socket_count].events= POLLIN; \ @@ -5792,6 +5793,8 @@ void handle_connections_sockets() delete thd; continue; } + + init_net_server_extension(thd); if (is_unix_sock) thd->security_ctx->host=(char*) my_localhost; @@ -7155,9 +7158,9 @@ SHOW_VAR status_vars[]= { {"Compression", (char*) &show_net_compression, SHOW_FUNC}, {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, {"Cpu_time", (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS}, - {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, + {"Created_tmp_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}, {"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}, @@ -7220,11 +7223,11 @@ SHOW_VAR status_vars[]= { #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}, + {"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}, #ifdef HAVE_REPLICATION {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC}, @@ -7234,10 +7237,10 @@ SHOW_VAR status_vars[]= { #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_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}, @@ -8585,6 +8588,43 @@ void refresh_status(THD *thd) mysql_mutex_unlock(&LOCK_thread_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} +}; +#endif /* HAVE_PSI_INTERFACE */ + PSI_stage_info stage_after_create= { 0, "After create", 0}; PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0}; PSI_stage_info stage_changing_master= { 0, "Changing master", 0}; @@ -8595,7 +8635,7 @@ PSI_stage_info stage_checking_query_cache_for_query= { 0, "checking query cache 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 MyISAM", 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}; @@ -8606,6 +8646,7 @@ 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}; @@ -8647,6 +8688,7 @@ PSI_stage_info stage_sending_cached_result_to_client= { 0, "sending cached resul PSI_stage_info stage_sending_data= { 0, "Sending data", 0}; PSI_stage_info stage_setup= { 0, "setup", 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}; @@ -8688,41 +8730,6 @@ PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an #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} -}; - PSI_stage_info *all_server_stages[]= { & stage_after_create, @@ -8746,6 +8753,7 @@ PSI_stage_info *all_server_stages[]= & 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, @@ -8787,6 +8795,7 @@ PSI_stage_info *all_server_stages[]= & stage_sending_data, & stage_setup, & stage_slave_has_read_all_relay_log, + & stage_sorting, & stage_sorting_for_group, & stage_sorting_for_order, & stage_sorting_result, diff --git a/sql/mysqld.h b/sql/mysqld.h index e2beb59908b..a5fe2fae7ed 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -318,6 +318,7 @@ extern PSI_stage_info stage_deleting_from_main_table; extern PSI_stage_info stage_deleting_from_reference_tables; extern PSI_stage_info stage_discard_or_import_tablespace; extern PSI_stage_info stage_end; +extern PSI_stage_info stage_enabling_keys; extern PSI_stage_info stage_executing; extern PSI_stage_info stage_execution_of_init_command; extern PSI_stage_info stage_explaining; @@ -358,6 +359,7 @@ extern PSI_stage_info stage_sending_cached_result_to_client; extern PSI_stage_info stage_sending_data; extern PSI_stage_info stage_setup; extern PSI_stage_info stage_slave_has_read_all_relay_log; +extern PSI_stage_info stage_sorting; extern PSI_stage_info stage_sorting_for_group; extern PSI_stage_info stage_sorting_for_order; extern PSI_stage_info stage_sorting_result; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index fc60df27689..7e9425f51f2 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2012, Monty Program Ab + Copyright (c) 2010, 2012, Monty Program Ab. 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 @@ -12,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @file @@ -112,11 +112,15 @@ extern void query_cache_insert(const char *packet, ulong length, #define update_statistics(A) #endif +#ifdef MYSQL_SERVER +/* Additional instrumentation hooks for the server */ +#include "mysql_com_server.h" +#endif + #define TEST_BLOCKING 8 #define MAX_PACKET_LENGTH (256L*256L*256L-1) -static my_bool net_write_buff(NET *net,const uchar *packet,ulong len); - +static my_bool net_write_buff(NET *, const uchar *, ulong); /** Init with packet info. */ @@ -139,10 +143,14 @@ my_bool my_net_init(NET *net, Vio* vio) net->net_skip_rest_factor= 0; net->last_errno=0; net->unused= 0; +#ifdef MYSQL_SERVER + net->extension= NULL; +#endif - if (vio != 0) /* If real connection */ + if (vio) { - net->fd = vio_fd(vio); /* For perl DBI/DBD */ + /* For perl DBI/DBD. */ + net->fd= vio_fd(vio); #if defined(MYSQL_SERVER) && !defined(__WIN__) if (!(test_flags & TEST_BLOCKING)) { @@ -262,7 +270,10 @@ static int net_data_is_ready(my_socket sd) #endif /* EMBEDDED_LIBRARY */ /** - Intialize NET handler for new reads: + Clear (reinitialize) the NET structure for a new command. + + @remark Performs debug checking of the socket buffer to + ensure that the protocol sequence is correct. - Read from socket until there is nothing more to read. Discard what is read. @@ -347,7 +358,7 @@ my_bool net_flush(NET *net) { error=test(net_real_write(net, net->buff, (size_t) (net->write_pos - net->buff))); - net->write_pos=net->buff; + net->write_pos= net->buff; } /* Sync packet number if using compression */ if (net->compress) @@ -363,15 +374,13 @@ my_bool net_flush(NET *net) /** Write a logical packet with packet header. - Format: Packet length (3 bytes), packet number(1 byte) - When compression is used a 3 byte compression length is added + Format: Packet length (3 bytes), packet number (1 byte) + When compression is used, a 3 byte compression length is added. - @note - If compression is used the original package is modified! + @note If compression is used, the original packet is modified! */ -my_bool -my_net_write(NET *net,const uchar *packet,size_t len) +my_bool my_net_write(NET *net, const uchar *packet, size_t len) { uchar buff[NET_HEADER_SIZE]; int rc; @@ -416,6 +425,7 @@ my_net_write(NET *net,const uchar *packet,size_t len) return rc; } + /** Send a command to the server. @@ -820,6 +830,19 @@ my_real_read(NET *net, size_t *complen) my_bool net_blocking=vio_is_blocking(net->vio); uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : NET_HEADER_SIZE); +#ifdef MYSQL_SERVER + size_t count= remain; + struct st_net_server *server_extension; + server_extension= static_cast<st_net_server*> (net->extension); + if (server_extension != NULL) + { + void *user_data= server_extension->m_user_data; + DBUG_ASSERT(server_extension->m_before_header != NULL); + DBUG_ASSERT(server_extension->m_after_header != NULL); + server_extension->m_before_header(net, user_data, count); + } +#endif + *complen = 0; net->reading_or_writing=1; @@ -976,6 +999,14 @@ my_real_read(NET *net, size_t *complen) } pos=net->buff + net->where_b; remain = (uint32) len; +#ifdef MYSQL_SERVER + if (server_extension != NULL) + { + void *user_data= server_extension->m_user_data; + server_extension->m_after_header(net, user_data, count, 0); + server_extension= NULL; + } +#endif } } @@ -992,6 +1023,14 @@ end: if (len != packet_error) DBUG_DUMP("data", net->buff+net->where_b, len); #endif +#ifdef MYSQL_SERVER + if (server_extension != NULL) + { + void *user_data= server_extension->m_user_data; + server_extension->m_after_header(net, user_data, count, 1); + DBUG_ASSERT(len == packet_error || len == 0); + } +#endif return(len); } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 9b09bb57358..c5b38fd4b1d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3849,7 +3849,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) /* STEP 1: Get temporary table name */ - statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status); + thd->inc_status_created_tmp_tables(); if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) temp_pool_slot = bitmap_lock_set_next(&temp_pool); diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 7b8f3142851..007ce2e6d15 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -371,8 +371,8 @@ public: These are the members we got from temptable creation code. We'll need them if we'll need to convert table from HEAP to MyISAM/Maria. */ - ENGINE_COLUMNDEF *start_recinfo; - ENGINE_COLUMNDEF *recinfo; + TMP_ENGINE_COLUMNDEF *start_recinfo; + TMP_ENGINE_COLUMNDEF *recinfo; SJ_TMP_TABLE *next_flush_table; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index abc22a00695..4eac3dcd4f5 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -44,7 +44,6 @@ ulong rpl_status=RPL_NULL; mysql_mutex_t LOCK_rpl_status; -mysql_cond_t COND_rpl_status; HASH slave_list; const char *rpl_role_type[] = {"MASTER","SLAVE",NullS}; @@ -70,7 +69,6 @@ void change_rpl_status(ulong from_status, ulong to_status) mysql_mutex_lock(&LOCK_rpl_status); if (rpl_status == from_status || rpl_status == RPL_ANY) rpl_status = to_status; - mysql_cond_signal(&COND_rpl_status); mysql_mutex_unlock(&LOCK_rpl_status); } diff --git a/sql/replication.h b/sql/replication.h index 8027c4830ec..510e56a3085 100644 --- a/sql/replication.h +++ b/sql/replication.h @@ -10,8 +10,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef REPLICATION_H #define REPLICATION_H @@ -460,34 +460,6 @@ int unregister_binlog_relay_io_observer(Binlog_relay_IO_observer *observer, void MYSQL *rpl_connect_master(MYSQL *mysql); /** - Set thread entering a condition - - This function should be called before putting a thread to wait for - a condition. @a mutex should be held before calling this - function. After being waken up, @f thd_exit_cond should be called. - - @param thd The thread entering the condition, NULL means current thread - @param cond The condition the thread is going to wait for - @param mutex The mutex associated with the condition, this must be - held before call this function - @param msg The new process message for the thread -*/ -const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, - mysql_mutex_t *mutex, const char *msg); - -/** - Set thread leaving a condition - - This function should be called after a thread being waken up for a - condition. - - @param thd The thread entering the condition, NULL means current thread - @param old_msg The process message, ususally this should be the old process - message before calling @f thd_enter_cond -*/ -void thd_exit_cond(MYSQL_THD thd, const char *old_msg); - -/** Get the value of user variable as an integer. This function will return the value of variable @a name as an diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index c1a4347d508..a765f851812 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -143,14 +143,30 @@ enum { /* 5.1.16 added value of master_ssl_verify_server_cert */ LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT= 15, - /* 6.0 added value of master_heartbeat_period */ + + /* 5.5 added value of master_heartbeat_period */ LINE_FOR_MASTER_HEARTBEAT_PERIOD= 16, + /* MySQL Cluster 6.3 added master_bind */ LINE_FOR_MASTER_BIND = 17, + /* 6.0 added value of master_ignore_server_id */ LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 18, + + /* 6.0 added value of master_uuid */ + LINE_FOR_MASTER_UUID= 19, + + /* line for master_retry_count */ + LINE_FOR_MASTER_RETRY_COUNT= 20, + + /* line for ssl_crl */ + LINE_FOR_SSL_CRL= 21, + + /* line for ssl_crl */ + LINE_FOR_SSL_CRLPATH= 22, + /* Number of lines currently used when saving master info file */ - LINES_IN_MASTER_INFO= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS + LINES_IN_MASTER_INFO= LINE_FOR_SSL_CRLPATH }; int init_master_info(Master_info* mi, const char* master_info_fname, @@ -384,6 +400,23 @@ file '%s')", fname); sql_print_error("Failed to initialize master info ignore_server_ids"); goto errwithmsg; } + + /* reserved */ + if (lines >= LINE_FOR_MASTER_UUID && + init_strvar_from_file(dummy_buf, sizeof(dummy_buf), &mi->file, "")) + goto errwithmsg; + + /* Starting from 5.5 the master_retry_count may be in the repository. */ + if (lines >= LINE_FOR_MASTER_RETRY_COUNT && + init_strvar_from_file(dummy_buf, sizeof(dummy_buf), &mi->file, "")) + goto errwithmsg; + + if (lines >= LINE_FOR_SSL_CRLPATH && + (init_strvar_from_file(mi->ssl_crl, sizeof(mi->ssl_crl), + &mi->file, "") || + init_strvar_from_file(mi->ssl_crlpath, sizeof(mi->ssl_crlpath), + &mi->file, ""))) + goto errwithmsg; } #ifndef HAVE_OPENSSL @@ -523,14 +556,16 @@ int flush_master_info(Master_info* mi, sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period); my_b_seek(file, 0L); my_b_printf(file, - "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n", + "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n", LINES_IN_MASTER_INFO, mi->master_log_name, llstr(mi->master_log_pos, lbuf), mi->host, mi->user, mi->password, mi->port, mi->connect_retry, (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert, - heartbeat_buf, "", ignore_server_ids_buf); + heartbeat_buf, "", ignore_server_ids_buf, + "", 0, + mi->ssl_crl, mi->ssl_crlpath); my_free(ignore_server_ids_buf); err= flush_io_cache(file); if (sync_masterinfo_period && !err && diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 252b4f3f5b9..d0d190d64dc 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2006, 2012, Oracle and/or its affiliates. + Copyright (c) 2010, 2012, Monty Program Ab. 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 @@ -10,8 +11,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #include "sql_priv.h" #include "unireg.h" // HAVE_* @@ -687,7 +688,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, ulong init_abort_pos_wait; int error=0; struct timespec abstime; // for timeout checking - const char *msg; + PSI_stage_info old_stage; DBUG_ENTER("Relay_log_info::wait_for_pos"); if (!inited) @@ -698,9 +699,9 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, set_timespec(abstime,timeout); mysql_mutex_lock(&data_lock); - msg= thd->enter_cond(&data_cond, &data_lock, - "Waiting for the slave SQL thread to " - "advance position"); + thd->ENTER_COND(&data_cond, &data_lock, + &stage_waiting_for_the_slave_thread_to_advance_position, + &old_stage); /* This function will abort when it notices that some CHANGE MASTER or RESET MASTER has changed the master info. @@ -844,7 +845,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, } err: - thd->exit_cond(msg); + thd->EXIT_COND(&old_stage); DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \ improper_arguments: %d timed_out: %d", thd->killed_errno(), diff --git a/sql/set_var.cc b/sql/set_var.cc index 8e2f90b9bfd..ceb1adb81de 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab + Copyright (c) 2008, 2012, Monty Program Ab 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,10 +14,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation -#endif - /* variable declarations are in sys_vars.cc now !!! */ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ @@ -493,6 +489,10 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type) if (type == OPT_GLOBAL && var->check_type(type)) continue; + /* don't show non-visible variables */ + if (var->not_visible()) + continue; + show->name= var->name.str; show->value= (char*) var; show->type= SHOW_SYS; @@ -533,6 +533,11 @@ sys_var *intern_find_sys_var(const char *str, uint length) */ var= (sys_var*) my_hash_search(&system_variable_hash, (uchar*) str, length ? length : strlen(str)); + + /* Don't show non-visible variables. */ + if (var && var->not_visible()) + return NULL; + return var; } diff --git a/sql/set_var.h b/sql/set_var.h index 1d07a1b73e9..f0beac0fa7f 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -112,6 +112,7 @@ public: int scope() const { return flags & SCOPE_MASK; } CHARSET_INFO *charset(THD *thd); bool is_readonly() const { return flags & READONLY; } + bool not_visible() const { return flags & INVISIBLE; } /** the following is only true for keycache variables, that support the syntax @@keycache_name.variable_name diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index eb3e5c91262..16a907a6eff 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -3288,45 +3288,45 @@ ER_NONEXISTING_GRANT 42000 swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s'" ukr "Повноважень не визначено для користувача '%-.48s' з хосту '%-.64s'" ER_TABLEACCESS_DENIED_ERROR 42000 - cze "%-.32s p-Bříkaz nepřístupný pro uživatele: '%-.48s'@'%-.64s' pro tabulku '%-.192s'" - dan "%-.32s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for tabellen '%-.192s'" - nla "%-.32s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor tabel '%-.192s'" - eng "%-.32s command denied to user '%-.48s'@'%-.64s' for table '%-.192s'" - jps "コマンド %-.32s は ユーザー '%-.48s'@'%-.64s' ,テーブル '%-.192s' に対して許可されていません", - est "%-.32s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tabelis '%-.192s'" - fre "La commande '%-.32s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la table '%-.192s'" - ger "%-.32s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' auf Tabelle '%-.192s'" - hun "%-.32s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" - ita "Comando %-.32s negato per l'utente: '%-.48s'@'%-.64s' sulla tabella '%-.192s'" - jpn "コマンド %-.32s は ユーザー '%-.48s'@'%-.64s' ,テーブル '%-.192s' に対して許可されていません" - kor "'%-.32s' 명령은 다음 사용자에게 거부되었습니다. : '%-.48s'@'%-.64s' for 테이블 '%-.192s'" - por "Comando '%-.32s' negado para o usuário '%-.48s'@'%-.64s' na tabela '%-.192s'" - rum "Comanda %-.32s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru tabela '%-.192s'" - rus "Команда %-.32s запрещена пользователю '%-.48s'@'%-.64s' для таблицы '%-.192s'" - serbian "%-.32s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za tabelu '%-.192s'" - spa "%-.32s comando negado para usuario: '%-.48s'@'%-.64s' para tabla '%-.192s'" - swe "%-.32s ej tillåtet för '%-.48s'@'%-.64s' för tabell '%-.192s'" - ukr "%-.32s команда заборонена користувачу: '%-.48s'@'%-.64s' у таблиці '%-.192s'" + cze "%-.128s p-Bříkaz nepřístupný pro uživatele: '%-.48s'@'%-.64s' pro tabulku '%-.192s'" + dan "%-.128s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for tabellen '%-.192s'" + nla "%-.128s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor tabel '%-.192s'" + eng "%-.128s command denied to user '%-.48s'@'%-.64s' for table '%-.192s'" + jps "コマンド %-.128s は ユーザー '%-.48s'@'%-.64s' ,テーブル '%-.192s' に対して許可されていません", + est "%-.128s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tabelis '%-.192s'" + fre "La commande '%-.128s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la table '%-.192s'" + ger "%-.128s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' auf Tabelle '%-.192s'" + hun "%-.128s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" + ita "Comando %-.128s negato per l'utente: '%-.48s'@'%-.64s' sulla tabella '%-.192s'" + jpn "コマンド %-.128s は ユーザー '%-.48s'@'%-.64s' ,テーブル '%-.192s' に対して許可されていません" + kor "'%-.128s' 명령은 다음 사용자에게 거부되었습니다. : '%-.48s'@'%-.64s' for 테이블 '%-.192s'" + por "Comando '%-.128s' negado para o usuário '%-.48s'@'%-.64s' na tabela '%-.192s'" + rum "Comanda %-.128s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru tabela '%-.192s'" + rus "Команда %-.128s запрещена пользователю '%-.48s'@'%-.64s' для таблицы '%-.192s'" + serbian "%-.128s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za tabelu '%-.192s'" + spa "%-.128s comando negado para usuario: '%-.48s'@'%-.64s' para tabla '%-.192s'" + swe "%-.128s ej tillåtet för '%-.48s'@'%-.64s' för tabell '%-.192s'" + ukr "%-.128s команда заборонена користувачу: '%-.48s'@'%-.64s' у таблиці '%-.192s'" ER_COLUMNACCESS_DENIED_ERROR 42000 - cze "%-.32s p-Bříkaz nepřístupný pro uživatele: '%-.48s'@'%-.64s' pro sloupec '%-.192s' v tabulce '%-.192s'" - dan "%-.32s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for kolonne '%-.192s' in tabellen '%-.192s'" - nla "%-.32s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor kolom '%-.192s' in tabel '%-.192s'" - eng "%-.32s command denied to user '%-.48s'@'%-.64s' for column '%-.192s' in table '%-.192s'" - jps "コマンド %-.32s は ユーザー '%-.48s'@'%-.64s'¥n カラム '%-.192s' テーブル '%-.192s' に対して許可されていません", - est "%-.32s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tulbale '%-.192s' tabelis '%-.192s'" - fre "La commande '%-.32s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la colonne '%-.192s' de la table '%-.192s'" - ger "%-.32s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' und Feld '%-.192s' in Tabelle '%-.192s'" - hun "%-.32s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' mezo eseten a '%-.192s' tablaban" - ita "Comando %-.32s negato per l'utente: '%-.48s'@'%-.64s' sulla colonna '%-.192s' della tabella '%-.192s'" - jpn "コマンド %-.32s は ユーザー '%-.48s'@'%-.64s'\n カラム '%-.192s' テーブル '%-.192s' に対して許可されていません" - kor "'%-.32s' 명령은 다음 사용자에게 거부되었습니다. : '%-.48s'@'%-.64s' for 칼럼 '%-.192s' in 테이블 '%-.192s'" - por "Comando '%-.32s' negado para o usuário '%-.48s'@'%-.64s' na coluna '%-.192s', na tabela '%-.192s'" - rum "Comanda %-.32s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru coloana '%-.192s' in tabela '%-.192s'" - rus "Команда %-.32s запрещена пользователю '%-.48s'@'%-.64s' для столбца '%-.192s' в таблице '%-.192s'" - serbian "%-.32s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za kolonu '%-.192s' iz tabele '%-.192s'" - spa "%-.32s comando negado para usuario: '%-.48s'@'%-.64s' para columna '%-.192s' en la tabla '%-.192s'" - swe "%-.32s ej tillåtet för '%-.48s'@'%-.64s' för kolumn '%-.192s' i tabell '%-.192s'" - ukr "%-.32s команда заборонена користувачу: '%-.48s'@'%-.64s' для стовбця '%-.192s' у таблиці '%-.192s'" + cze "%-.128s p-Bříkaz nepřístupný pro uživatele: '%-.48s'@'%-.64s' pro sloupec '%-.192s' v tabulce '%-.192s'" + dan "%-.128s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for kolonne '%-.192s' in tabellen '%-.192s'" + nla "%-.128s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor kolom '%-.192s' in tabel '%-.192s'" + eng "%-.128s command denied to user '%-.48s'@'%-.64s' for column '%-.192s' in table '%-.192s'" + jps "コマンド %-.128s は ユーザー '%-.48s'@'%-.64s'¥n カラム '%-.192s' テーブル '%-.192s' に対して許可されていません", + est "%-.128s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tulbale '%-.192s' tabelis '%-.192s'" + fre "La commande '%-.128s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la colonne '%-.192s' de la table '%-.192s'" + ger "%-.128s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' und Feld '%-.192s' in Tabelle '%-.192s'" + hun "%-.128s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' mezo eseten a '%-.192s' tablaban" + ita "Comando %-.128s negato per l'utente: '%-.48s'@'%-.64s' sulla colonna '%-.192s' della tabella '%-.192s'" + jpn "コマンド %-.128s は ユーザー '%-.48s'@'%-.64s'\n カラム '%-.192s' テーブル '%-.192s' に対して許可されていません" + kor "'%-.128s' 명령은 다음 사용자에게 거부되었습니다. : '%-.48s'@'%-.64s' for 칼럼 '%-.192s' in 테이블 '%-.192s'" + por "Comando '%-.128s' negado para o usuário '%-.48s'@'%-.64s' na coluna '%-.192s', na tabela '%-.192s'" + rum "Comanda %-.128s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru coloana '%-.192s' in tabela '%-.192s'" + rus "Команда %-.128s запрещена пользователю '%-.48s'@'%-.64s' для столбца '%-.192s' в таблице '%-.192s'" + serbian "%-.128s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za kolonu '%-.192s' iz tabele '%-.192s'" + spa "%-.128s comando negado para usuario: '%-.48s'@'%-.64s' para columna '%-.192s' en la tabla '%-.192s'" + swe "%-.128s ej tillåtet för '%-.48s'@'%-.64s' för kolumn '%-.192s' i tabell '%-.192s'" + ukr "%-.128s команда заборонена користувачу: '%-.48s'@'%-.64s' для стовбця '%-.192s' у таблиці '%-.192s'" ER_ILLEGAL_GRANT_FOR_TABLE 42000 cze "Neplatn-Bý příkaz GRANT/REVOKE. Prosím, přečtěte si v manuálu, jaká privilegia je možné použít." dan "Forkert GRANT/REVOKE kommando. Se i brugervejledningen hvilke privilegier der kan specificeres." @@ -5330,8 +5330,8 @@ ER_VIEW_CHECK_FAILED rus "проверка CHECK OPTION для VIEW '%-.192s.%-.192s' провалилась" ukr "Перевірка CHECK OPTION для VIEW '%-.192s.%-.192s' не пройшла" ER_PROCACCESS_DENIED_ERROR 42000 - eng "%-.32s command denied to user '%-.48s'@'%-.64s' for routine '%-.192s'" - ger "Befehl %-.32s nicht zulässig für Benutzer '%-.48s'@'%-.64s' in Routine '%-.192s'" + eng "%-.128s command denied to user '%-.48s'@'%-.64s' for routine '%-.192s'" + ger "Befehl %-.128s nicht zulässig für Benutzer '%-.48s'@'%-.64s' in Routine '%-.192s'" ER_RELAY_LOG_FAIL eng "Failed purging old relay logs: %s" ger "Bereinigen alter Relais-Logs fehlgeschlagen: %s" @@ -5912,10 +5912,12 @@ ER_EVENT_OPEN_TABLE_FAILED ER_EVENT_NEITHER_M_EXPR_NOR_M_AT eng "No datetime expression provided" ger "Kein DATETIME-Ausdruck angegeben" -ER_COL_COUNT_DOESNT_MATCH_CORRUPTED + +ER_UNUSED_2 eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted" ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschädigt" -ER_CANNOT_LOAD_FROM_TABLE + +ER_UNUSED_3 eng "Cannot load from mysql.%s. The table is probably corrupted" ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt" ER_EVENT_CANNOT_DELETE @@ -5944,7 +5946,7 @@ ER_CANT_WRITE_LOCK_LOG_TABLE ER_CANT_LOCK_LOG_TABLE eng "You can't use locks with log tables." ger "Log-Tabellen können nicht gesperrt werden." -ER_FOREIGN_DUPLICATE_KEY 23000 S1009 +ER_UNUSED_4 eng "Upholding foreign key constraints for table '%.192s', entry '%-.192s', key %d would lead to a duplicate entry" ger "Aufrechterhalten der Fremdschlüssel-Beschränkungen für Tabelle '%.192s', Eintrag '%-.192s', Schlüssel %d würde zu einem doppelten Eintrag führen" ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE @@ -6070,8 +6072,8 @@ ER_EVENT_CANNOT_CREATE_IN_THE_PAST eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation." ger "Ausführungszeit des Events liegt in der Vergangenheit, und es wurde ON COMPLETION NOT PRESERVE gesetzt. Das Event wurde unmittelbar nach Erzeugung gelöscht." ER_EVENT_CANNOT_ALTER_IN_THE_PAST - eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation." - ger "Ausführungszeit des Events liegt in der Vergangenheit, und es wurde ON COMPLETION NOT PRESERVE gesetzt. Das Event wurde unmittelbar nach Erzeugung gelöscht." + eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was not changed. Specify a time in the future." + ger "Execution Zeitpunkt des Ereignisses in der Vergangenheit liegt, und es war NACH ABSCHLUSS Set nicht erhalten. Die Veranstaltung wurde nicht verändert. Geben Sie einen Zeitpunkt in der Zukunft." ER_SLAVE_INCIDENT eng "The incident %s occured on the master. Message: %-.64s" ger "Der Vorfall %s passierte auf dem Master. Meldung: %-.64s" @@ -6485,6 +6487,7 @@ ER_PLUGIN_NO_UNINSTALL ER_PLUGIN_NO_INSTALL eng "Plugin '%s' is marked as not dynamically installable. You have to stop the server to install it." + ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT eng "Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave." @@ -6515,6 +6518,7 @@ ER_CANNOT_LOAD_FROM_TABLE_V2 eng "Cannot load from %s.%s. The table is probably corrupted" ger "Kann %s.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt" + ER_MASTER_DELAY_VALUE_OUT_OF_RANGE eng "The requested value %u for the master delay exceeds the maximum %u" ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT diff --git a/sql/slave.cc b/sql/slave.cc index b0a21317adf..36a3d51b497 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -487,7 +487,19 @@ static void set_thd_in_use_temporary_tables(Relay_log_info *rli) TABLE *table; for (table= rli->save_temporary_tables ; table ; table= table->next) + { table->in_use= rli->sql_thd; + if (table->file != NULL) + { + /* + Since we are stealing opened temporary tables from one thread to another, + we need to let the performance schema know that, + for aggregates per thread to work properly. + */ + table->file->unbind_psi(); + table->file->rebind_psi(); + } + } } int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) @@ -515,7 +527,7 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) DBUG_PRINT("info",("Flushing relay-log info file.")); if (current_thd) - thd_proc_info(current_thd, "Flushing relay-log info file."); + THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file); if (flush_relay_log_info(&mi->rli)) DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); @@ -539,7 +551,7 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) DBUG_PRINT("info",("Flushing relay log and master info file.")); if (current_thd) - thd_proc_info(current_thd, "Flushing relay log and master info files."); + THD_STAGE_INFO(current_thd, stage_flushing_relay_log_and_master_info_repository); if (flush_master_info(mi, TRUE, FALSE)) DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); @@ -719,8 +731,10 @@ int start_slave_thread( while (start_id == *slave_run_id) { DBUG_PRINT("sleep",("Waiting for slave thread to start")); - const char *old_msg= thd->enter_cond(start_cond, cond_lock, - "Waiting for slave thread to start"); + PSI_stage_info saved_stage= {0, "", 0}; + thd->ENTER_COND(start_cond, cond_lock, + & stage_waiting_for_slave_thread_to_start, + & saved_stage); /* It is not sufficient to test this at loop bottom. We must test it after registering the mutex in enter_cond(). If the kill @@ -730,7 +744,7 @@ int start_slave_thread( */ if (!thd->killed) mysql_cond_wait(start_cond, cond_lock); - thd->exit_cond(old_msg); + thd->EXIT_COND(& saved_stage); mysql_mutex_lock(cond_lock); // re-acquire it as exit_cond() released if (thd->killed) { @@ -1781,15 +1795,15 @@ static bool wait_for_relay_log_space(Relay_log_info* rli) { bool slave_killed=0; Master_info* mi = rli->mi; - const char *save_proc_info; + PSI_stage_info old_stage; THD* thd = mi->io_thd; DBUG_ENTER("wait_for_relay_log_space"); mysql_mutex_lock(&rli->log_space_lock); - save_proc_info= thd->enter_cond(&rli->log_space_cond, - &rli->log_space_lock, - "\ -Waiting for the slave SQL thread to free enough relay log space"); + thd->ENTER_COND(&rli->log_space_cond, + &rli->log_space_lock, + &stage_waiting_for_relay_log_space, + &old_stage); while (rli->log_space_limit < rli->log_space_total && !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) @@ -1844,7 +1858,7 @@ Waiting for the slave SQL thread to free enough relay log space"); rli->ignore_log_space_limit= false; } - thd->exit_cond(save_proc_info); + thd->EXIT_COND(&old_stage); DBUG_RETURN(slave_killed); } @@ -2082,7 +2096,7 @@ bool show_master_info(THD* thd, Master_info* mi) non-volotile members like mi->io_thd, which is guarded by the mutex. */ mysql_mutex_lock(&mi->run_lock); - protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); + protocol->store(mi->io_thd ? mi->io_thd->get_proc_info() : "", &my_charset_bin); mysql_mutex_unlock(&mi->run_lock); mysql_mutex_lock(&mi->data_lock); @@ -2318,9 +2332,9 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) } if (thd_type == SLAVE_THD_SQL) - thd_proc_info(thd, "Waiting for the next event in relay log"); + THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log); else - thd_proc_info(thd, "Waiting for master update"); + THD_STAGE_INFO(thd, stage_waiting_for_master_update); thd->set_time(); /* Do not use user-supplied timeout value for system threads. */ thd->variables.lock_wait_timeout= LONG_TIMEOUT; @@ -2344,7 +2358,6 @@ static inline bool slave_sleep(THD *thd, time_t seconds, bool ret; struct timespec abstime; - const char *old_proc_info; mysql_mutex_t *lock= &info->sleep_lock; mysql_cond_t *cond= &info->sleep_cond; @@ -2352,7 +2365,7 @@ static inline bool slave_sleep(THD *thd, time_t seconds, /* Absolute system time at which the sleep time expires. */ set_timespec(abstime, seconds); mysql_mutex_lock(lock); - old_proc_info= thd->enter_cond(cond, lock, thd->proc_info); + thd->ENTER_COND(cond, lock, NULL, NULL); while (! (ret= func(thd, info))) { @@ -2361,7 +2374,7 @@ static inline bool slave_sleep(THD *thd, time_t seconds, break; } /* Implicitly unlocks the mutex. */ - thd->exit_cond(old_proc_info); + thd->EXIT_COND(NULL); return ret; } @@ -3070,7 +3083,7 @@ pthread_handler_t handle_slave_io(void *arg) goto err; } - thd_proc_info(thd, "Connecting to master"); + THD_STAGE_INFO(thd, stage_connecting_to_master); // we can get killed during safe_connect if (!safe_connect(thd, mysql, mi)) { @@ -3107,7 +3120,7 @@ connected: // TODO: the assignment below should be under mutex (5.0) mi->slave_running= MYSQL_SLAVE_RUN_CONNECT; thd->slave_net = &mysql->net; - thd_proc_info(thd, "Checking master version"); + THD_STAGE_INFO(thd, stage_checking_master_version); ret= get_master_version_and_clock(mysql, mi); if (ret == 1) /* Fatal error */ @@ -3131,7 +3144,7 @@ connected: /* Register ourselves with the master. */ - thd_proc_info(thd, "Registering slave on master"); + THD_STAGE_INFO(thd, stage_registering_slave_on_master); if (register_slave_on_master(mysql, mi, &suppress_warnings)) { if (!check_io_slave_killed(thd, mi, "Slave I/O thread killed " @@ -3161,7 +3174,7 @@ connected: DBUG_PRINT("info",("Starting reading binary log from master")); while (!io_slave_killed(thd,mi)) { - thd_proc_info(thd, "Requesting binlog dump"); + THD_STAGE_INFO(thd, stage_requesting_binlog_dump); if (request_dump(thd, mysql, mi, &suppress_warnings)) { sql_print_error("Failed on request_dump()"); @@ -3194,7 +3207,7 @@ requesting master dump") || important thing is to not confuse users by saying "reading" whereas we're in fact receiving nothing. */ - thd_proc_info(thd, "Waiting for master to send event"); + THD_STAGE_INFO(thd, stage_waiting_for_master_to_send_event); event_len= read_event(mysql, mi, &suppress_warnings); if (check_io_slave_killed(thd, mi, "Slave I/O thread killed while \ reading event")) @@ -3242,7 +3255,7 @@ Stopping slave I/O thread due to out-of-memory error from master"); } // if (event_len == packet_error) retry_count=0; // ok event, reset retry counter - thd_proc_info(thd, "Queueing master event to the relay log"); + THD_STAGE_INFO(thd, stage_queueing_master_event_to_the_relay_log); event_buf= (const char*)mysql->net.read_pos + 1; if (RUN_HOOK(binlog_relay_io, after_read_event, (thd, mi,(const char*)mysql->net.read_pos + 1, @@ -3339,7 +3352,7 @@ err: mi->mysql=0; } write_ignored_events_info_to_relay_log(thd, mi); - thd_proc_info(thd, "Waiting for slave mutex on exit"); + THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); mysql_mutex_lock(&mi->run_lock); err_during_init: @@ -3615,7 +3628,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, while (!sql_slave_killed(thd,rli)) { - thd_proc_info(thd, "Reading event from the relay log"); + THD_STAGE_INFO(thd, stage_reading_event_from_the_relay_log); DBUG_ASSERT(rli->sql_thd == thd); THD_CHECK_SENTRY(thd); @@ -3727,7 +3740,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ thd->catalog= 0; thd->reset_query(); thd->reset_db(NULL, 0); - thd_proc_info(thd, "Waiting for slave mutex on exit"); + THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); mysql_mutex_lock(&rli->run_lock); err_during_init: /* We need data_lock, at least to wake up any waiting master_pos_wait() */ diff --git a/sql/sp.cc b/sql/sp.cc index 29195234a5a..1a2e3bd49ab 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -377,7 +377,7 @@ void Proc_table_intact::report_error(uint code, const char *fmt, ...) if (code) my_message(code, buf, MYF(0)); else - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc"); + my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "proc"); if (m_print_once) { @@ -1429,9 +1429,9 @@ public: MYSQL_ERROR ** cond_hdl) { if (sql_errno == ER_NO_SUCH_TABLE || - sql_errno == ER_CANNOT_LOAD_FROM_TABLE || + sql_errno == ER_CANNOT_LOAD_FROM_TABLE_V2 || sql_errno == ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE || - sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED) + sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2) return true; return false; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 41c04b9c413..c2cfb6f5477 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab + Copyright (c) 2009, 2011, Monty Program Ab 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 @@ -12,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* @@ -750,10 +750,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) acl_cache->clear(1); // Clear locked hostname cache init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); - if (init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, - FALSE)) + if (init_read_record(&read_record_info, thd, table= tables[0].table, + NULL, 1, 1, FALSE)) goto end; - table->use_all_columns(); (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50); while (!(read_record_info.read_record(&read_record_info))) @@ -802,10 +801,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_hosts); - if (init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0, - FALSE)) + if (init_read_record(&read_record_info, thd, table=tables[1].table, + NULL, 1, 1, FALSE)) goto end; - table->use_all_columns(); (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100); password_length= table->field[2]->field_length / @@ -1004,10 +1002,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_users); - if (init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0, - FALSE)) + if (init_read_record(&read_record_info, thd, table=tables[2].table, + NULL, 1, 1, FALSE)) goto end; - table->use_all_columns(); (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100); while (!(read_record_info.read_record(&read_record_info))) @@ -1070,8 +1067,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) 50, 100); if (tables[3].table) { - init_read_record(&read_record_info, thd, table= tables[3].table, NULL, 1, - 0, FALSE); + if (init_read_record(&read_record_info, thd, table= tables[3].table, + NULL, 1, 1, FALSE)) + goto end; table->use_all_columns(); while (!(read_record_info.read_record(&read_record_info))) { @@ -1304,7 +1302,7 @@ static ulong get_sort(uint count,...) chars= 128; // Marker that chars existed } } - sort= (sort << 8) + (wild_pos ? min(wild_pos, 127) : chars); + sort= (sort << 8) + (wild_pos ? min(wild_pos, 127U) : chars); } va_end(args); return sort; @@ -3939,7 +3937,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, db_name= table_list->db; table_name= table_list->table_name; - grant_name= routine_hash_search(Str->host.str, NullS, db_name, Str->user.str, table_name, is_proc, 1); if (!grant_name) @@ -4093,6 +4090,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, result= TRUE; continue; } + /* No User, but a password? They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... ! @@ -4100,6 +4098,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, */ if (!tmp_Str->user.str && tmp_Str->password.str) Str->password= tmp_Str->password; + if (replace_user_table(thd, tables[0].table, *Str, (!db ? rights : 0), revoke_grant, create_new_users, test(thd->variables.sql_mode & @@ -5683,7 +5682,7 @@ void get_privilege_desc(char *to, uint max_length, ulong access) { uint pos; char *start=to; - DBUG_ASSERT(max_length >= 30); // For end ',' removal + DBUG_ASSERT(max_length >= 30); // For end ', ' removal if (access) { @@ -5694,9 +5693,11 @@ void get_privilege_desc(char *to, uint max_length, ulong access) command_lengths[pos] + (uint) (to-start) < max_length) { to= strmov(to, command_array[pos]); - *to++=','; + *to++= ','; + *to++= ' '; } } + to--; // Remove end ' ' to--; // Remove end ',' } *to=0; @@ -9201,6 +9202,13 @@ bool acl_authenticate(THD *thd, uint connect_errors, else my_ok(thd); +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_CALL(set_thread_user_host)(thd->main_security_ctx.user, + strlen(thd->main_security_ctx.user), + thd->main_security_ctx.host_or_ip, + strlen(thd->main_security_ctx.host_or_ip)); +#endif + /* Ready to handle queries */ DBUG_RETURN(0); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1942878d9be..7ce77bcf9b4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -529,6 +529,7 @@ static void table_def_unuse_table(TABLE *table) DBUG_ASSERT(! table->s->has_old_version()); table->in_use= 0; + /* Remove table from the list of tables used in this share. */ table->s->used_tables.remove(table); /* Add table to the list of unused TABLE objects for this share. */ @@ -627,6 +628,13 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, DBUG_RETURN(0); } share->ref_count++; // Mark in use + +#ifdef HAVE_PSI_TABLE_INTERFACE + share->m_psi= PSI_CALL(get_table_share)(false, share); +#else + share->m_psi= NULL; +#endif + DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u", (ulong) share, share->ref_count)); DBUG_RETURN(share); @@ -1630,6 +1638,10 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) table->file->ha_reset(); } + /* Do this *before* entering the LOCK_open critical section. */ + if (table->file != NULL) + table->file->unbind_psi(); + mysql_mutex_lock(&LOCK_open); if (table->s->has_old_version() || table->needs_reopen() || @@ -2724,6 +2736,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, int error; TABLE_SHARE *share; my_hash_value_type hash_value; + bool recycled_free_table; + DBUG_ENTER("open_table"); /* an open table operation needs a lot of the stack space */ @@ -3033,6 +3047,11 @@ retry_share: DBUG_RETURN(TRUE); } + /* + Check if this TABLE_SHARE-object corresponds to a view. Note, that there is + no need to call TABLE_SHARE::has_old_version() as we do for regular tables, + because view shares are always up to date. + */ if (share->is_view) { /* @@ -3142,6 +3161,7 @@ retry_share: { table= share->free_tables.front(); table_def_use_table(thd, table); + recycled_free_table= true; /* We need to release share as we have EXTRA reference to it in our hands. */ release_table_share(share); } @@ -3153,6 +3173,7 @@ retry_share: mysql_mutex_unlock(&LOCK_open); + recycled_free_table= false; /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) goto err_lock; @@ -3194,6 +3215,13 @@ retry_share: mysql_mutex_unlock(&LOCK_open); + /* Call rebind_psi outside of the LOCK_open critical section. */ + if (recycled_free_table) + { + DBUG_ASSERT(table->file != NULL); + table->file->rebind_psi(); + } + table->mdl_ticket= mdl_ticket; table->next= thd->open_tables; /* Link into simple list */ @@ -4914,7 +4942,7 @@ restart: table_to_open= start; sroutine_to_open= (Sroutine_hash_entry**) &thd->lex->sroutines_list.first; *counter= 0; - thd_proc_info(thd, "Opening tables"); + THD_STAGE_INFO(thd, stage_opening_tables); /* If we are executing LOCK TABLES statement or a DDL statement @@ -5105,7 +5133,6 @@ restart: } err: - thd_proc_info(thd, 0); free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block if (error && *table_to_open) @@ -5479,7 +5506,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, /* should not be used in a prelocked_mode context, see NOTE above */ DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED); - thd_proc_info(thd, "Opening table"); + THD_STAGE_INFO(thd, stage_opening_tables); thd->current_tablenr= 0; /* open_ltable can be used only for BASIC TABLEs */ table_list->required_type= FRMTYPE_TABLE; @@ -5548,7 +5575,6 @@ end: trans_rollback_stmt(thd); close_thread_tables(thd); } - thd_proc_info(thd, 0); DBUG_RETURN(table); } @@ -5796,7 +5822,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, query_table->lock_type >= TL_WRITE_ALLOW_WRITE && unique_keys > 1 && thd->lex->sql_command == SQLCOM_INSERT && /* Duplicate key update is not supported by INSERT DELAYED */ - thd->command != COM_DELAYED_INSERT && + thd->get_command() != COM_DELAYED_INSERT && thd->lex->duplicates == DUP_UPDATE) thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); } @@ -6033,8 +6059,21 @@ TABLE *open_table_uncached(THD *thd, const char *path, const char *db, init_tmp_table_share(thd, share, saved_cache_key, key_length, strend(saved_cache_key)+1, tmp_path); - if (open_table_def(thd, share, 0) || - open_table_from_share(thd, share, table_name, + if (open_table_def(thd, share, 0)) + { + /* No need to lock share->mutex as this is not needed for tmp tables */ + free_table_share(share); + my_free(tmp_table); + DBUG_RETURN(0); + } + +#ifdef HAVE_PSI_TABLE_INTERFACE + share->m_psi= PSI_CALL(get_table_share)(true, share); +#else + share->m_psi= NULL; +#endif + + if (open_table_from_share(thd, share, table_name, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, @@ -9394,7 +9433,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)); Item_func_match *ifm; DBUG_PRINT("info",("Performing FULLTEXT search")); - thd_proc_info(thd, "FULLTEXT initialization"); + THD_STAGE_INFO(thd, stage_fulltext_initialization); while ((ifm=li++)) ifm->init_search(no_order); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 96814562757..354898a7cf2 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2010, 2012, Monty Program Ab. 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 @@ -10,8 +11,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /* Description of the query cache: @@ -411,23 +412,28 @@ const uchar *query_state_map; struct Query_cache_wait_state { THD *m_thd; - const char *m_proc_info; + PSI_stage_info m_old_stage; + const char *m_func; + const char *m_file; + int m_line; Query_cache_wait_state(THD *thd, const char *func, const char *file, unsigned int line) : m_thd(thd), - m_proc_info(NULL) + m_old_stage(), + m_func(func), m_file(file), m_line(line) { if (m_thd) - m_proc_info= set_thd_proc_info(m_thd, - "Waiting for query cache lock", - func, file, line); + set_thd_stage_info(m_thd, + &stage_waiting_for_query_cache_lock, + &m_old_stage, + m_func, m_file, m_line); } ~Query_cache_wait_state() { if (m_thd) - set_thd_proc_info(m_thd, m_proc_info, NULL, NULL, 0); + set_thd_stage_info(m_thd, &m_old_stage, NULL, m_func, m_file, m_line); } }; @@ -1140,7 +1146,7 @@ Query_cache::abort(Query_cache_tls *query_cache_tls) if (query_block) { thd= current_thd; - thd_proc_info(thd, "storing result in query cache"); + THD_STAGE_INFO(thd, stage_storing_result_in_query_cache); DUMP(this); BLOCK_LOCK_WR(query_block); // The following call will remove the lock on query_block @@ -1191,7 +1197,7 @@ void Query_cache::end_of_result(THD *thd) suitable size if needed and setting block type. Since this is the last block, the writer should be dropped. */ - thd_proc_info(thd, "storing result in query cache"); + THD_STAGE_INFO(thd, stage_storing_result_in_query_cache); DUMP(this); BLOCK_LOCK_WR(query_block); Query_cache_query *header= query_block->query(); @@ -1847,7 +1853,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length) DBUG_PRINT("qcache", ("No active database")); } - thd_proc_info(thd, "checking query cache for query"); + THD_STAGE_INFO(thd, stage_checking_query_cache_for_query); // fill all gaps between fields with 0 to get repeatable key bzero(&flags, QUERY_CACHE_FLAGS_SIZE); @@ -1938,7 +1944,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", } // Check access; - thd_proc_info(thd, "checking privileges on cached query"); + THD_STAGE_INFO(thd, stage_checking_privileges_on_cached_query); block_table= query_block->table(0); block_table_end= block_table+query_block->n_tables; for (; block_table != block_table_end; block_table++) @@ -2044,7 +2050,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", Send cached result to client */ #ifndef EMBEDDED_LIBRARY - thd_proc_info(thd, "sending cached result to client"); + THD_STAGE_INFO(thd, stage_sending_cached_result_to_client); do { DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)", @@ -2145,7 +2151,7 @@ void Query_cache::invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used) for (; tables_used; tables_used= tables_used->next) { - thd_proc_info(thd, "invalidating query cache entries (table list)"); + THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table_list); invalidate_table(thd, (uchar*) tables_used->key, tables_used->key_length); DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key, tables_used->key+ @@ -2174,7 +2180,7 @@ void Query_cache::invalidate_locked_for_write(THD *thd, for (; tables_used; tables_used= tables_used->next_local) { - thd_proc_info(thd, "invalidating query cache entries (table)"); + THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table); if (tables_used->lock_type >= TL_WRITE_ALLOW_WRITE && tables_used->table) { @@ -2302,6 +2308,9 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename) { DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename"); + if (is_disabled()) + DBUG_VOID_RETURN; + /* Calculate the key outside the lock to make the lock shorter */ char key[MAX_DBKEY_LENGTH]; uint32 db_length; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3a3cf4520e1..9c3e0f8f9dd 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -510,14 +510,14 @@ const char *set_thd_proc_info(THD *thd_arg, const char *info, } extern "C" -void set_thd_stage_info(void *opaque_thd, +void set_thd_stage_info(void *thd_arg, const PSI_stage_info *new_stage, PSI_stage_info *old_stage, const char *calling_func, const char *calling_file, const unsigned int calling_line) { - THD *thd= (THD*) opaque_thd; + THD *thd= (THD*) thd_arg; if (thd == NULL) thd= current_thd; @@ -558,24 +558,26 @@ void THD::enter_stage(const PSI_stage_info *new_stage, return; } - -extern "C" -const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, - mysql_mutex_t *mutex, const char *msg) +void thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, mysql_mutex_t *mutex, + const PSI_stage_info *stage, PSI_stage_info *old_stage, + const char *src_function, const char *src_file, + int src_line) { if (!thd) thd= current_thd; - return thd->enter_cond(cond, mutex, msg); + return thd->enter_cond(cond, mutex, stage, old_stage, src_function, src_file, + src_line); } -extern "C" -void thd_exit_cond(MYSQL_THD thd, const char *old_msg) +void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage, + const char *src_function, const char *src_file, + int src_line) { if (!thd) thd= current_thd; - thd->exit_cond(old_msg); + thd->exit_cond(stage, src_function, src_file, src_line); return; } @@ -789,7 +791,7 @@ THD::THD() first_successful_insert_id_in_prev_stmt_for_binlog(0), first_successful_insert_id_in_cur_stmt(0), stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE), - examined_row_count(0), + m_examined_row_count(0), accessed_rows_and_keys(0), warning_info(&main_warning_info), stmt_da(&main_da), @@ -841,7 +843,7 @@ THD::THD() my_hash_clear(&handler_tables_hash); tmp_table=0; cuted_fields= 0L; - sent_row_count= 0L; + m_sent_row_count= 0L; limit_found_rows= 0; m_row_count_func= -1; statement_id_counter= 0UL; @@ -902,7 +904,7 @@ THD::THD() where= THD::DEFAULT_WHERE; server_id = ::server_id; slave_net = 0; - command=COM_CONNECT; + m_command=COM_CONNECT; *scramble= '\0'; /* Call to init() below requires fully initialized Open_tables_state. */ @@ -2335,7 +2337,7 @@ int select_send::send_data(List<Item> &items) DBUG_RETURN(TRUE); } - thd->sent_row_count++; + thd->inc_sent_row_count(1); if (thd->vio_ok()) DBUG_RETURN(protocol->write()); @@ -2427,7 +2429,7 @@ select_to_file::~select_to_file() select_export::~select_export() { - thd->sent_row_count=row_count; + thd->set_sent_row_count(row_count); } @@ -4133,8 +4135,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->enable_slow_log= enable_slow_log; backup->query_plan_flags= query_plan_flags; backup->limit_found_rows= limit_found_rows; - backup->examined_row_count= examined_row_count; - backup->sent_row_count= sent_row_count; + backup->examined_row_count= m_examined_row_count; + backup->sent_row_count= m_sent_row_count; backup->cuted_fields= cuted_fields; backup->client_capabilities= client_capabilities; backup->savepoints= transaction.savepoints; @@ -4157,8 +4159,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, /* Disable result sets */ client_capabilities &= ~CLIENT_MULTI_RESULTS; in_sub_stmt|= new_state; - examined_row_count= 0; - sent_row_count= 0; + m_examined_row_count= 0; + m_sent_row_count= 0; cuted_fields= 0; transaction.savepoints= 0; first_successful_insert_id_in_cur_stmt= 0; @@ -4205,7 +4207,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) first_successful_insert_id_in_cur_stmt= backup->first_successful_insert_id_in_cur_stmt; limit_found_rows= backup->limit_found_rows; - sent_row_count= backup->sent_row_count; + set_sent_row_count(backup->sent_row_count); client_capabilities= backup->client_capabilities; /* If we've left sub-statement mode, reset the fatal error flag. @@ -4223,7 +4225,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) The following is added to the old values as we are interested in the total complexity of the query */ - examined_row_count+= backup->examined_row_count; + inc_examined_row_count(backup->examined_row_count); cuted_fields+= backup->cuted_fields; DBUG_VOID_RETURN; } @@ -4238,31 +4240,31 @@ void THD::set_statement(Statement *stmt) void THD::set_sent_row_count(ha_rows count) { - sent_row_count= count; - MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, sent_row_count); + m_sent_row_count= count; + MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); } void THD::set_examined_row_count(ha_rows count) { - examined_row_count= count; - MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, examined_row_count); + m_examined_row_count= count; + MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count); } void THD::inc_sent_row_count(ha_rows count) { - sent_row_count+= count; - MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, sent_row_count); + m_sent_row_count+= count; + MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); } void THD::inc_examined_row_count(ha_rows count) { - examined_row_count+= count; - MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, examined_row_count); + m_examined_row_count+= count; + MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count); } void THD::inc_status_created_tmp_disk_tables() { - status_var_increment(status_var.created_tmp_disk_tables); + status_var_increment(status_var.created_tmp_disk_tables_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_created_tmp_disk_tables)(m_statement_psi, 1); #endif @@ -4270,7 +4272,7 @@ void THD::inc_status_created_tmp_disk_tables() void THD::inc_status_created_tmp_tables() { - status_var_increment(status_var.created_tmp_tables); + status_var_increment(status_var.created_tmp_tables_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_created_tmp_tables)(m_statement_psi, 1); #endif @@ -4278,7 +4280,7 @@ void THD::inc_status_created_tmp_tables() void THD::inc_status_select_full_join() { - status_var_increment(status_var.select_full_join_count); + status_var_increment(status_var.select_full_join_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_select_full_join)(m_statement_psi, 1); #endif @@ -4286,7 +4288,7 @@ void THD::inc_status_select_full_join() void THD::inc_status_select_full_range_join() { - status_var_increment(status_var.select_full_range_join_count); + status_var_increment(status_var.select_full_range_join_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_select_full_range_join)(m_statement_psi, 1); #endif @@ -4294,7 +4296,7 @@ void THD::inc_status_select_full_range_join() void THD::inc_status_select_range() { - status_var_increment(status_var.select_range_count); + status_var_increment(status_var.select_range_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_select_range)(m_statement_psi, 1); #endif @@ -4302,7 +4304,7 @@ void THD::inc_status_select_range() void THD::inc_status_select_range_check() { - status_var_increment(status_var.select_range_check_count); + status_var_increment(status_var.select_range_check_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_select_range_check)(m_statement_psi, 1); #endif @@ -4310,7 +4312,7 @@ void THD::inc_status_select_range_check() void THD::inc_status_select_scan() { - status_var_increment(status_var.select_scan_count); + status_var_increment(status_var.select_scan_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_select_scan)(m_statement_psi, 1); #endif @@ -4318,7 +4320,7 @@ void THD::inc_status_select_scan() void THD::inc_status_sort_merge_passes() { - status_var_increment(status_var.filesort_merge_passes); + status_var_increment(status_var.filesort_merge_passes_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_sort_merge_passes)(m_statement_psi, 1); #endif @@ -4326,7 +4328,7 @@ void THD::inc_status_sort_merge_passes() void THD::inc_status_sort_range() { - status_var_increment(status_var.filesort_range_count); + status_var_increment(status_var.filesort_range_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_sort_range)(m_statement_psi, 1); #endif @@ -4334,7 +4336,7 @@ void THD::inc_status_sort_range() void THD::inc_status_sort_rows(ha_rows count) { - statistic_add(status_var.filesort_rows, count, &LOCK_status); + statistic_add(status_var.filesort_rows_, count, &LOCK_status); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_sort_rows)(m_statement_psi, count); #endif @@ -4342,7 +4344,7 @@ void THD::inc_status_sort_rows(ha_rows count) void THD::inc_status_sort_scan() { - status_var_increment(status_var.filesort_scan_count); + status_var_increment(status_var.filesort_scan_count_); #ifdef HAVE_PSI_STATEMENT_INTERFACE PSI_CALL(inc_statement_sort_scan)(m_statement_psi, 1); #endif @@ -4366,9 +4368,9 @@ void THD::set_status_no_good_index_used() void THD::set_command(enum enum_server_command command_arg) { - command= command_arg; + m_command= command_arg; #ifdef HAVE_PSI_THREAD_INTERFACE - PSI_CALL(set_thread_command)(command); + PSI_CALL(set_thread_command)(m_command); #endif } @@ -4379,6 +4381,10 @@ void THD::set_query(const CSET_STRING &string_arg) mysql_mutex_lock(&LOCK_thd_data); set_query_inner(string_arg); mysql_mutex_unlock(&LOCK_thd_data); + +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_CALL(set_thread_info)(query(), query_length()); +#endif } /** Assign a new value to thd->query and thd->query_id. */ diff --git a/sql/sql_class.h b/sql/sql_class.h index b21f60a7a78..6c218a58109 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -13,18 +13,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SQL_CLASS_INCLUDED #define SQL_CLASS_INCLUDED /* Classes in mysql */ -#ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ -#endif - #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #ifdef MYSQL_SERVER #include "unireg.h" // REQUIRED: for other includes @@ -49,6 +44,17 @@ #include <mysql/psi/mysql_table.h> #include <mysql_com_server.h> +extern "C" +void set_thd_stage_info(void *thd, + const PSI_stage_info *new_stage, + PSI_stage_info *old_stage, + const char *calling_func, + const char *calling_file, + const unsigned int calling_line); + +#define THD_STAGE_INFO(thd, stage) \ + (thd)->enter_stage(& stage, NULL, __func__, __FILE__, __LINE__) + class Reprepare_observer; class Relay_log_info; @@ -71,7 +77,7 @@ enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT, SLAVE_EXEC_MODE_IDEMPOTENT, - SLAVE_EXEC_MODE_LAST_BIT}; + SLAVE_EXEC_MODE_LAST_BIT }; enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY, SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY}; enum enum_mark_columns @@ -594,8 +600,8 @@ typedef struct system_status_var { ulong com_other; ulong com_stat[(uint) SQLCOM_END]; - ulong created_tmp_disk_tables; - ulong created_tmp_tables; + ulong created_tmp_disk_tables_; + ulong created_tmp_tables_; ulong ha_commit_count; ulong ha_delete_count; ulong ha_read_first_count; @@ -643,16 +649,16 @@ typedef struct system_status_var ulong net_big_packet_count; ulong opened_tables; ulong opened_shares; - ulong select_full_join_count; - ulong select_full_range_join_count; - ulong select_range_count; - ulong select_range_check_count; - ulong select_scan_count; + ulong select_full_join_count_; + ulong select_full_range_join_count_; + ulong select_range_count_; + ulong select_range_check_count_; + ulong select_scan_count_; ulong long_query_count; - ulong filesort_merge_passes; - ulong filesort_range_count; - ulong filesort_rows; - ulong filesort_scan_count; + ulong filesort_merge_passes_; + ulong filesort_range_count_; + ulong filesort_rows_; + ulong filesort_scan_count_; /* Prepared statements and binary protocol */ ulong com_stmt_prepare; ulong com_stmt_reprepare; @@ -1693,11 +1699,14 @@ public: uint dbug_sentry; // watch out for memory corruption #endif struct st_my_thread_var *mysys_var; +private: /* Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from first byte of the packet in do_command() */ - enum enum_server_command command; + enum enum_server_command m_command; + +public: uint32 server_id; uint32 file_id; // for LOAD DATA INFILE /* remote (peer) port */ @@ -2112,11 +2121,12 @@ public: ha_rows cuted_fields; +private: /* number of rows we actually sent to the client, including "synthetic" rows in ROLLUP etc. */ - ha_rows sent_row_count; + ha_rows m_sent_row_count; /** Number of rows read and/or evaluated for a statement. Used for @@ -2128,12 +2138,14 @@ public: statement including ORDER BY could possibly evaluate the row in filesort() before reading it for e.g. update. */ - ha_rows examined_row_count; - /** - The number of rows and/or keys examined by the query, both read, - changed or written. - */ - ulonglong accessed_rows_and_keys; + ha_rows m_examined_row_count; + +public: + ha_rows get_sent_row_count() const + { return m_sent_row_count; } + + ha_rows get_examined_row_count() const + { return m_examined_row_count; } void set_sent_row_count(ha_rows count); void set_examined_row_count(ha_rows count); @@ -2155,6 +2167,13 @@ public: void inc_status_sort_scan(); void set_status_no_index_used(); void set_status_no_good_index_used(); + + /** + The number of rows and/or keys examined by the query, both read, + changed or written. + */ + ulonglong accessed_rows_and_keys; + /** Check if the number of rows accessed by a statement exceeded LIMIT ROWS EXAMINED. If so, signal the query engine to stop execution. @@ -2472,22 +2491,20 @@ public: int errcode); #endif - /* - For enter_cond() / exit_cond() to work the mutex must be got before - enter_cond(); this mutex is then released by exit_cond(). - Usage must be: lock mutex; enter_cond(); your code; exit_cond(). - */ - inline const char* enter_cond(mysql_cond_t *cond, mysql_mutex_t* mutex, - const char* msg) + inline void + enter_cond(mysql_cond_t *cond, mysql_mutex_t* mutex, + const PSI_stage_info *stage, PSI_stage_info *old_stage, + const char *src_function, const char *src_file, + int src_line) { - const char* old_msg = proc_info; mysql_mutex_assert_owner(mutex); mysys_var->current_mutex = mutex; mysys_var->current_cond = cond; - proc_info = msg; - return old_msg; + enter_stage(stage, old_stage, src_function, src_file, src_line); } - inline void exit_cond(const char* old_msg) + inline void exit_cond(const PSI_stage_info *stage, + const char *src_function, const char *src_file, + int src_line) { /* Putting the mutex unlock in thd->exit_cond() ensures that @@ -2499,7 +2516,7 @@ public: mysql_mutex_lock(&mysys_var->mutex); mysys_var->current_mutex = 0; mysys_var->current_cond = 0; - proc_info = old_msg; + enter_stage(stage, NULL, src_function, src_file, src_line); mysql_mutex_unlock(&mysys_var->mutex); return; } @@ -2511,6 +2528,9 @@ public: my_hrtime_t hrtime= my_hrtime(); start_time= hrtime_to_my_time(hrtime); start_time_sec_part= hrtime_sec_part(hrtime); +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_CALL(set_thread_start_time)(start_time); +#endif } inline void set_start_time() { @@ -2518,6 +2538,9 @@ public: { start_time= hrtime_to_my_time(user_time); start_time_sec_part= hrtime_sec_part(user_time); +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_CALL(set_thread_start_time)(start_time); +#endif } else set_current_time(); @@ -2892,6 +2915,7 @@ public: */ bool set_db(const char *new_db, size_t new_db_len) { + bool result; /* Do not reallocate memory if current chunk is big enough. */ if (db && new_db && db_length >= new_db_len) memcpy(db, new_db, new_db_len+1); @@ -2904,7 +2928,12 @@ public: db= NULL; } db_length= db ? new_db_len : 0; - return new_db && !db; + result= new_db && !db; +#ifdef HAVE_PSI_THREAD_INTERFACE + if (result) + PSI_CALL(set_thread_db)(new_db, new_db_len); +#endif + return result; } /** @@ -2922,6 +2951,9 @@ public: { db= new_db; db_length= new_db_len; +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_CALL(set_thread_db)(new_db, new_db_len); +#endif } /* Copy the current database to the argument. Use the current arena to @@ -3040,7 +3072,7 @@ public: virtual void set_statement(Statement *stmt); void set_command(enum enum_server_command command); inline enum enum_server_command get_command() const - { return command; } + { return m_command; } /** Assign a new value to thd->query and thd->query_id and mysys_var. @@ -3497,12 +3529,18 @@ public: #ifdef WITH_ARIA_STORAGE_ENGINE #include <maria.h> +#else +#undef USE_ARIA_FOR_TMP_TABLES #endif #ifdef USE_ARIA_FOR_TMP_TABLES -#define ENGINE_COLUMNDEF MARIA_COLUMNDEF +#define TMP_ENGINE_COLUMNDEF MARIA_COLUMNDEF +#define TMP_ENGINE_HTON maria_hton +#define TMP_ENGINE_NAME "Aria" #else -#define ENGINE_COLUMNDEF MI_COLUMNDEF +#define TMP_ENGINE_COLUMNDEF MI_COLUMNDEF +#define TMP_ENGINE_HTON myisam_hton +#define TMP_ENGINE_NAME "MyISAM" #endif /* @@ -3525,7 +3563,7 @@ public: Copy_field *save_copy_field, *save_copy_field_end; uchar *group_buff; Item **items_to_copy; /* Fields in tmp table */ - ENGINE_COLUMNDEF *recinfo, *start_recinfo; + TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo; KEY *keyinfo; ha_rows end_write_records; /** @@ -4244,114 +4282,6 @@ inline void handler::decrement_statistics(ulong SSV::*offset) const status_var_decrement(table->in_use->status_var.*offset); } -inline int handler::ha_index_read_map(uchar * buf, const uchar * key, - key_part_map keypart_map, - enum ha_rkey_function find_flag) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_key_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_read_map(buf, key, keypart_map, - find_flag); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - - -/* - @note: Other index lookup/navigation functions require prior - handler->index_init() call. This function is different, it requires - that the scan is not initialized, and accepts "uint index" as an argument. -*/ - -inline int handler::ha_index_read_idx_map(uchar * buf, uint index, - const uchar * key, - key_part_map keypart_map, - enum ha_rkey_function find_flag) -{ - int error; - DBUG_ASSERT(inited==NONE); - increment_statistics(&SSV::ha_read_key_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, index, 0, - { error= index_read_idx_map(buf, index, key, keypart_map, - find_flag); }) - if (!error) - { - update_rows_read(); - index_rows_read[index]++; - } - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_index_next(uchar * buf) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_next_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_next(buf); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_index_prev(uchar * buf) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_prev_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_prev(buf); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_index_first(uchar * buf) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_first_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_first(buf); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_index_last(uchar * buf) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_last_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_last(buf); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_index_next_same(uchar *buf, const uchar *key, - uint keylen) -{ - int error; - DBUG_ASSERT(inited==INDEX); - increment_statistics(&SSV::ha_read_next_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0, - { error= index_next_same(buf, key, keylen); }) - if (!error) - update_index_statistics(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} inline int handler::ha_ft_read(uchar *buf) { @@ -4363,37 +4293,6 @@ inline int handler::ha_ft_read(uchar *buf) return error; } -inline int handler::ha_rnd_next(uchar *buf) -{ - int error; - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0, - { error= rnd_next(buf); }) - if (!error) - { - update_rows_read(); - increment_statistics(&SSV::ha_read_rnd_next_count); - } - else if (error == HA_ERR_RECORD_DELETED) - increment_statistics(&SSV::ha_read_rnd_deleted_count); - else - increment_statistics(&SSV::ha_read_rnd_next_count); - - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -inline int handler::ha_rnd_pos(uchar *buf, uchar *pos) -{ - int error; - increment_statistics(&SSV::ha_read_rnd_count); - MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0, - { error= rnd_pos(buf, pos); }) - if (!error) - update_rows_read(); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - inline int handler::ha_rnd_pos_by_record(uchar *buf) { int error= rnd_pos_by_record(buf); @@ -4436,16 +4335,50 @@ inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data) extern pthread_attr_t *get_connection_attrib(void); -extern "C" -void set_thd_stage_info(void *thd, - const PSI_stage_info *new_stage, - PSI_stage_info *old_stage, - const char *calling_func, - const char *calling_file, - const unsigned int calling_line); - -#define THD_STAGE_INFO(thd, stage) \ - (thd)->enter_stage(& stage, NULL, __func__, __FILE__, __LINE__) +/** + Set thread entering a condition + + This function should be called before putting a thread to wait for + a condition. @a mutex should be held before calling this + function. After being waken up, @f thd_exit_cond should be called. + + @param thd The thread entering the condition, NULL means current thread + @param cond The condition the thread is going to wait for + @param mutex The mutex associated with the condition, this must be + held before call this function + @param stage The new process message for the thread + @param old_stage The old process message for the thread + @param src_function The caller source function name + @param src_file The caller source file name + @param src_line The caller source line number +*/ +void thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, mysql_mutex_t *mutex, + const PSI_stage_info *stage, PSI_stage_info *old_stage, + const char *src_function, const char *src_file, + int src_line); + +#define THD_ENTER_COND(P1, P2, P3, P4, P5) \ + thd_enter_cond(P1, P2, P3, P4, P5, __func__, __FILE__, __LINE__) + +/** + Set thread leaving a condition + + This function should be called after a thread being waken up for a + condition. + + @param thd The thread entering the condition, NULL means current thread + @param stage The process message, ususally this should be the old process + message before calling @f thd_enter_cond + @param src_function The caller source function name + @param src_file The caller source file name + @param src_line The caller source line number +*/ +void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage, + const char *src_function, const char *src_file, + int src_line); + +#define THD_EXIT_COND(P1, P2) \ + thd_exit_cond(P1, P2, __func__, __FILE__, __LINE__) #endif /* MYSQL_SERVER */ diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 81a85f10a16..dcc63a80b25 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1096,7 +1096,7 @@ void prepare_new_connection_state(THD* thd) TODO: refactor this to avoid code duplication there */ thd->proc_info= 0; - thd->command= COM_SLEEP; + thd->set_command(COM_SLEEP); thd->set_time(); thd->init_for_queries(); @@ -1241,6 +1241,7 @@ void do_handle_one_connection(THD *thd_arg) { bool create_user= TRUE; + mysql_socket_set_thread_owner(thd->net.vio->mysql_socket); if (thd_prepare_connection(thd)) { create_user= FALSE; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5128b1284dd..c87c9382630 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -87,7 +87,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(TRUE); } - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); table->map=1; if (mysql_prepare_delete(thd, table_list, &conds)) @@ -226,7 +226,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, /* If running in safe sql mode, don't allow updates without keys */ if (table->quick_keys.is_clear_all()) { - thd->server_status|=SERVER_QUERY_NO_INDEX_USED; + thd->set_status_no_index_used(); if (safe_update && !using_limit) { delete select; @@ -273,7 +273,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, free_underlaid_joins(thd, &thd->lex->select_lex); DBUG_RETURN(TRUE); } - thd->examined_row_count+= examined_rows; + thd->inc_examined_row_count(examined_rows); /* Filesort has already found and selected the rows we want to delete, so we don't need the where clause @@ -304,7 +304,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, init_read_record_idx(&info, thd, table, 1, usable_index, reverse); init_ftfuncs(thd, select_lex, 1); - thd_proc_info(thd, "updating"); + THD_STAGE_INFO(thd, stage_updating); if (table->triggers && table->triggers->has_triggers(TRG_EVENT_DELETE, @@ -329,7 +329,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, { if (table->vfield) update_virtual_fields(thd, table); - thd->examined_row_count++; + thd->inc_examined_row_count(1); // thd->is_error() is tested to disallow delete row on error if (!select || select->skip_record(thd) > 0) { @@ -380,7 +380,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->file->print_error(loc_error,MYF(0)); error=1; } - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); end_read_record(&info); if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_NORMAL); @@ -624,7 +624,7 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_ENTER("multi_delete::prepare"); unit= u; do_delete= 1; - thd_proc_info(thd, "deleting from main table"); + THD_STAGE_INFO(thd, stage_deleting_from_main_table); SELECT_LEX *select_lex= u->first_select(); if (select_lex->first_cond_optimization) { @@ -1014,7 +1014,7 @@ int multi_delete::do_table_deletes(TABLE *table, bool ignore) bool multi_delete::send_eof() { killed_state killed_status= NOT_KILLED; - thd_proc_info(thd, "deleting from reference tables"); + THD_STAGE_INFO(thd, stage_deleting_from_reference_tables); /* Does deletes for the last n - 1 tables, returns 0 if ok */ int local_error= do_deletes(); // returns 0 if success @@ -1023,7 +1023,7 @@ bool multi_delete::send_eof() local_error= local_error || error; killed_status= (local_error == 0)? NOT_KILLED : thd->killed; /* reset used flags */ - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); if (thd->transaction.stmt.modified_non_trans_table) thd->transaction.all.modified_non_trans_table= TRUE; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index adc3d9d875a..023792dddd0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -750,7 +750,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, lock_type= table_list->lock_type; - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); thd->lex->used_tables=0; values= its++; value_count= values->elements; @@ -835,7 +835,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #endif error=0; - thd_proc_info(thd, "update"); + THD_STAGE_INFO(thd, stage_update); if (duplic == DUP_REPLACE && (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); @@ -1086,7 +1086,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); } - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); /* We'll report to the client this id: - if the table contains an autoincrement column and we successfully @@ -1970,7 +1970,7 @@ public: strmake(thd.security_ctx->priv_user, thd.security_ctx->user, USERNAME_LENGTH); thd.current_tablenr=0; - thd.command=COM_DELAYED_INSERT; + thd.set_command(COM_DELAYED_INSERT); thd.lex->current_select= 0; // for my_message_sql thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() /* @@ -2058,7 +2058,7 @@ I_List<Delayed_insert> delayed_threads; static Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) { - thd_proc_info(thd, "waiting for delay_list"); + THD_STAGE_INFO(thd, stage_waiting_for_delay_list); mysql_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; @@ -2140,7 +2140,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, */ if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); - thd_proc_info(thd, "Creating delayed handler"); + THD_STAGE_INFO(thd, stage_creating_delayed_handler); mysql_mutex_lock(&LOCK_delayed_create); /* The first search above was done without LOCK_delayed_create. @@ -2201,14 +2201,14 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, handler thread has been properly initialized before exiting. Otherwise we risk doing clone_ticket() on a ticket that is no longer valid. */ - thd_proc_info(thd, "waiting for handler open"); + THD_STAGE_INFO(thd, stage_waiting_for_handler_open); while (!di->handler_thread_initialized || (!di->thd.killed && !di->table && !thd->killed)) { mysql_cond_wait(&di->cond_client, &di->mutex); } mysql_mutex_unlock(&di->mutex); - thd_proc_info(thd, "got old table"); + THD_STAGE_INFO(thd, stage_got_old_table); if (thd->killed) { di->unlock(); @@ -2290,13 +2290,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) tables_in_use++; if (!thd.lock) // Table is not locked { - thd_proc_info(client_thd, "waiting for handler lock"); + THD_STAGE_INFO(client_thd, stage_waiting_for_handler_lock); mysql_cond_signal(&cond); // Tell handler to lock table while (!thd.killed && !thd.lock && ! client_thd->killed) { mysql_cond_wait(&cond_client, &mutex); } - thd_proc_info(client_thd, "got handler lock"); + THD_STAGE_INFO(client_thd, stage_got_handler_lock); if (client_thd->killed) goto error; if (thd.killed) @@ -2330,7 +2330,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) bytes. Since the table copy is used for creating one record only, the other record buffers and alignment are unnecessary. */ - thd_proc_info(client_thd, "allocating local table"); + THD_STAGE_INFO(client_thd, stage_allocating_local_table); copy_tmp= (char*) client_thd->alloc(sizeof(*copy)+ (share->fields+1)*sizeof(Field**)+ share->reclength + @@ -2419,11 +2419,11 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, (ulong) query.length)); - thd_proc_info(thd, "waiting for handler insert"); + THD_STAGE_INFO(thd, stage_waiting_for_handler_insert); mysql_mutex_lock(&di->mutex); while (di->stacked_inserts >= delayed_queue_size && !thd->killed) mysql_cond_wait(&di->cond_client, &di->mutex); - thd_proc_info(thd, "storing row into queue"); + THD_STAGE_INFO(thd, stage_storing_row_into_queue); if (thd->killed) goto err; @@ -2781,7 +2781,7 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Information for pthread_kill */ di->thd.mysys_var->current_mutex= &di->mutex; di->thd.mysys_var->current_cond= &di->cond; - thd_proc_info(&(di->thd), "Waiting for INSERT"); + THD_STAGE_INFO(&(di->thd), stage_waiting_for_insert); DBUG_PRINT("info",("Waiting for someone to insert rows")); while (!thd->killed && !di->status) @@ -2812,7 +2812,6 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_mutex_unlock(&di->thd.mysys_var->mutex); mysql_mutex_lock(&di->mutex); } - thd_proc_info(&(di->thd), 0); if (di->tables_in_use && ! thd->lock && !thd->killed) { @@ -2939,7 +2938,7 @@ bool Delayed_insert::handle_inserts(void) table->next_number_field=table->found_next_number_field; table->use_all_columns(); - thd_proc_info(&thd, "upgrading lock"); + THD_STAGE_INFO(&thd, stage_upgrading_lock); if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock, thd.variables.lock_wait_timeout)) { @@ -2953,7 +2952,7 @@ bool Delayed_insert::handle_inserts(void) goto err; } - thd_proc_info(&thd, "insert"); + THD_STAGE_INFO(&thd, stage_insert); max_rows= delayed_insert_limit; if (thd.killed || table->s->has_old_version()) { @@ -3091,7 +3090,7 @@ bool Delayed_insert::handle_inserts(void) { if (tables_in_use) mysql_cond_broadcast(&cond_client); // If waiting clients - thd_proc_info(&thd, "reschedule"); + THD_STAGE_INFO(&thd, stage_reschedule); mysql_mutex_unlock(&mutex); if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { @@ -3114,13 +3113,12 @@ bool Delayed_insert::handle_inserts(void) if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); mysql_mutex_lock(&mutex); - thd_proc_info(&thd, "insert"); + THD_STAGE_INFO(&thd, stage_insert); } if (tables_in_use) mysql_cond_broadcast(&cond_client); // If waiting clients } } - thd_proc_info(&thd, 0); mysql_mutex_unlock(&mutex); /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 887bace6c42..18fa3203c64 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -605,7 +605,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, thd->profiling.set_query_source(buf, len); #endif - thd_proc_info(thd, "Execution of init_command"); + THD_STAGE_INFO(thd, stage_execution_of_init_command); save_client_capabilities= thd->client_capabilities; thd->client_capabilities|= CLIENT_MULTI_QUERIES; /* @@ -641,7 +641,6 @@ static void handle_bootstrap_impl(THD *thd) thd->thread_stack= (char*) &thd; #endif /* EMBEDDED_LIBRARY */ - thd_proc_info(thd, 0); thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0; /* @@ -1258,7 +1257,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* PSI begin */ thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, - com_statement_info[command]. m_key, + com_statement_info[command].m_key, thd->db, thd->db_length); THD_STAGE_INFO(thd, stage_init); MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt, @@ -1608,7 +1607,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, log_slow_statement(thd); - thd_proc_info(thd, "cleaning up"); + THD_STAGE_INFO(thd, stage_cleaning_up); thd->reset_query(); thd->set_command(COM_SLEEP); @@ -1617,7 +1616,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->m_statement_psi= NULL; dec_thread_running(); - thd_proc_info(thd, 0); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); @@ -1672,16 +1670,15 @@ void log_slow_statement(THD *thd) if (thd->enable_slow_log) { ulonglong end_utime_of_query= thd->current_utime(); - thd_proc_info(thd, "logging slow query"); if (((thd->server_status & SERVER_QUERY_WAS_SLOW) || ((thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && opt_log_queries_not_using_indexes && !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) && - thd->examined_row_count >= thd->variables.min_examined_row_limit) + thd->get_examined_row_count() >= thd->variables.min_examined_row_limit) { - thd_proc_info(thd, "logging slow query"); + THD_STAGE_INFO(thd, stage_logging_slow_query); thd->status_var.long_query_count++; slow_log_print(thd, thd->query(), thd->query_length(), end_utime_of_query); @@ -3251,7 +3248,7 @@ end_with_restore_list: if (add_item_to_list(thd, new Item_null())) goto error; - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0))) break; @@ -4654,7 +4651,7 @@ create_sp_error: my_ok(thd); break; } - thd_proc_info(thd, "query end"); + THD_STAGE_INFO(thd, stage_query_end); thd->update_stats(); /* @@ -4710,9 +4707,8 @@ finish: lex->unit.cleanup(); /* Free tables */ - thd_proc_info(thd, "closing tables"); + THD_STAGE_INFO(thd, stage_closing_tables); close_thread_tables(thd); - thd_proc_info(thd, 0); #ifndef DBUG_OFF if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt) @@ -4813,9 +4809,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) } } /* Count number of empty select queries */ - if (!thd->sent_row_count) + if (!thd->get_sent_row_count()) status_var_increment(thd->status_var.empty_queries); - status_var_add(thd->status_var.rows_sent, thd->sent_row_count); + status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count()); return res; } @@ -5031,7 +5027,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, dummy= 0; } - thd_proc_info(thd, "checking permissions"); + THD_STAGE_INFO(thd, stage_checking_permissions); if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) { DBUG_PRINT("error",("No database")); @@ -5652,7 +5648,7 @@ void THD::reset_for_next_command(bool calculate_userstat) thd->stmt_da->reset_diagnostics_area(); thd->warning_info->reset_for_next_command(); thd->rand_used= 0; - thd->sent_row_count= thd->examined_row_count= 0; + thd->m_sent_row_count= thd->m_examined_row_count= 0; thd->accessed_rows_and_keys= 0; /* Copy data for user stats */ @@ -5943,7 +5939,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, query_cache_abort(&thd->query_cache_tls); } - thd_proc_info(thd, "freeing items"); + THD_STAGE_INFO(thd, stage_freeing_items); sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size); sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size); thd->end_statement(); @@ -6780,7 +6776,7 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal) I_List_iterator<THD> it(threads); while ((tmp=it++)) { - if (tmp->command == COM_DAEMON) + if (tmp->get_command() == COM_DAEMON) continue; if (tmp->thread_id == id) { @@ -6860,7 +6856,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, I_List_iterator<THD> it(threads); while ((tmp=it++)) { - if (tmp->command == COM_DAEMON) + if (tmp->get_command() == COM_DAEMON) continue; /* Check that hostname (if given) and user name matches. diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index b579474ee4d..778d8ba6708 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2814,7 +2814,7 @@ void mysqld_stmt_reset(THD *thd, char *packet) stmt->state= Query_arena::STMT_PREPARED; - general_log_print(thd, thd->command, NullS); + general_log_print(thd, thd->get_command(), NullS); my_ok(thd); @@ -2847,7 +2847,7 @@ void mysqld_stmt_close(THD *thd, char *packet) */ DBUG_ASSERT(! stmt->is_in_use()); stmt->deallocate(); - general_log_print(thd, thd->command, NullS); + general_log_print(thd, thd->get_command(), NullS); DBUG_VOID_RETURN; } @@ -2962,7 +2962,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) thd->stmt_da= save_stmt_da; thd->warning_info= save_warinig_info; - general_log_print(thd, thd->command, NullS); + general_log_print(thd, thd->get_command(), NullS); DBUG_VOID_RETURN; } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index fafa7a4389e..039dd046086 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -587,7 +587,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, return NULL; } - thd_proc_info(thd, "Sending binlog event to slave"); + THD_STAGE_INFO(thd, stage_sending_binlog_event_to_slave); pos= my_b_tell(log); if (RUN_HOOK(binlog_transmit, before_send_event, @@ -1040,7 +1040,7 @@ impossible position"; #ifndef DBUG_OFF ulong hb_info_counter= 0; #endif - const char* old_msg= thd->proc_info; + PSI_stage_info old_stage; signal_cnt= mysql_bin_log.signal_cnt; do { @@ -1049,9 +1049,9 @@ impossible position"; DBUG_ASSERT(heartbeat_ts); set_timespec_nsec(*heartbeat_ts, heartbeat_period); } - thd->enter_cond(log_cond, log_lock, - "Master has sent all binlog to slave; " - "waiting for binlog to be updated"); + thd->ENTER_COND(log_cond, log_lock, + &stage_master_has_sent_all_binlog_to_slave, + &old_stage); ret= mysql_bin_log.wait_for_update_bin_log(thd, heartbeat_ts); DBUG_ASSERT(ret == 0 || (heartbeat_period != 0)); if (ret == ETIMEDOUT || ret == ETIME) @@ -1068,14 +1068,14 @@ impossible position"; /* reset transmit packet for the heartbeat event */ if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg)) { - thd->exit_cond(old_msg); + thd->EXIT_COND(&old_stage); goto err; } if (send_heartbeat_event(net, packet, p_coord, current_checksum_alg)) { errmsg = "Failed on my_net_write()"; my_errno= ER_UNKNOWN_ERROR; - thd->exit_cond(old_msg); + thd->EXIT_COND(&old_stage); goto err; } } @@ -1084,7 +1084,7 @@ impossible position"; DBUG_PRINT("wait",("binary log received update or a broadcast signal caught")); } } while (signal_cnt == mysql_bin_log.signal_cnt && !thd->killed); - thd->exit_cond(old_msg); + thd->EXIT_COND(&old_stage); } break; @@ -1111,7 +1111,7 @@ impossible position"; bool loop_breaker = 0; /* need this to break out of the for loop from switch */ - thd_proc_info(thd, "Finished reading one binlog; switching to next binlog"); + THD_STAGE_INFO(thd, stage_finished_reading_one_binlog_switching_to_next_binlog); switch (mysql_bin_log.find_next_log(&linfo, 1)) { case 0: break; @@ -1164,7 +1164,7 @@ end: RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags)); my_eof(thd); - thd_proc_info(thd, "Waiting to finalize termination"); + THD_STAGE_INFO(thd, stage_waiting_to_finalize_termination); mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; mysql_mutex_unlock(&LOCK_thread_count); @@ -1172,7 +1172,7 @@ end: DBUG_VOID_RETURN; err: - thd_proc_info(thd, "Waiting to finalize termination"); + THD_STAGE_INFO(thd, stage_waiting_to_finalize_termination); if (my_errno == ER_MASTER_FATAL_ERROR_READING_BINLOG && my_b_inited(&log)) { /* @@ -1372,7 +1372,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0)) DBUG_RETURN(1); - thd_proc_info(thd, "Killing slave"); + THD_STAGE_INFO(thd, stage_killing_slave); int thread_mask; lock_slave_threads(mi); // Get a mask of _running_ threads @@ -1399,7 +1399,6 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) ER(ER_SLAVE_WAS_NOT_RUNNING)); } unlock_slave_threads(mi); - thd_proc_info(thd, 0); if (slave_errno) { @@ -1520,7 +1519,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id) while ((tmp=it++)) { - if (tmp->command == COM_BINLOG_DUMP && + if (tmp->get_command() == COM_BINLOG_DUMP && tmp->server_id == slave_server_id) { mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete @@ -1575,7 +1574,7 @@ bool change_master(THD* thd, Master_info* mi) goto err; } - thd_proc_info(thd, "Changing master"); + THD_STAGE_INFO(thd, stage_changing_master); /* We need to check if there is an empty master_host. Otherwise change master succeeds, a master.info file is created containing @@ -1693,10 +1692,15 @@ bool change_master(THD* thd, Master_info* mi) strmake(mi->ssl_cipher, lex_mi->ssl_cipher, sizeof(mi->ssl_cipher)-1); if (lex_mi->ssl_key) strmake(mi->ssl_key, lex_mi->ssl_key, sizeof(mi->ssl_key)-1); + if (lex_mi->ssl_crl) + strmake(mi->ssl_crl, lex_mi->ssl_crl, sizeof(mi->ssl_crl)-1); + if (lex_mi->ssl_crlpath) + strmake(mi->ssl_crlpath, lex_mi->ssl_crlpath, sizeof(mi->ssl_crlpath)-1); + #ifndef HAVE_OPENSSL if (lex_mi->ssl || lex_mi->ssl_ca || lex_mi->ssl_capath || lex_mi->ssl_cert || lex_mi->ssl_cipher || lex_mi->ssl_key || - lex_mi->ssl_verify_server_cert ) + lex_mi->ssl_verify_server_cert || lex_mi->ssl_crl || lex_mi->ssl_crlpath) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SLAVE_IGNORED_SSL_PARAMS, ER(ER_SLAVE_IGNORED_SSL_PARAMS)); #endif @@ -1761,7 +1765,7 @@ bool change_master(THD* thd, Master_info* mi) if (need_relay_log_purge) { relay_log_purge= 1; - thd_proc_info(thd, "Purging old relay logs"); + THD_STAGE_INFO(thd, stage_purging_old_relay_logs); if (purge_relay_logs(&mi->rli, thd, 0 /* not only reset, but also reinit */, &errmsg)) @@ -1832,7 +1836,6 @@ bool change_master(THD* thd, Master_info* mi) err: unlock_slave_threads(mi); - thd_proc_info(thd, 0); if (ret == FALSE) my_ok(thd); DBUG_RETURN(ret); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7032fdae939..7f32ca0337e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -64,8 +64,6 @@ const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "index_merge", "hash_ALL", "hash_range", "hash_index", "hash_index_merge" }; -const char *copy_to_tmp_table= "Copying to tmp table"; - struct st_sargable_param; static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array); @@ -150,9 +148,6 @@ static COND *optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value, COND_EQUAL **cond_equal); bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); -static bool create_internal_tmp_table_from_heap2(THD *, TABLE *, - ENGINE_COLUMNDEF *, ENGINE_COLUMNDEF **, - int, bool, handlerton *, const char *); static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table, Procedure *proc); @@ -956,7 +951,7 @@ JOIN::optimize() optimized= 1; DEBUG_SYNC(thd, "before_join_optimize"); - thd_proc_info(thd, "optimizing"); + THD_STAGE_INFO(thd, stage_optimizing); set_allowed_join_cache_types(); need_distinct= TRUE; @@ -1196,7 +1191,7 @@ JOIN::optimize() sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables); /* Calculate how to do the join */ - thd_proc_info(thd, "statistics"); + THD_STAGE_INFO(thd, stage_statistics); if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) || thd->is_fatal_error) { @@ -1221,7 +1216,7 @@ JOIN::optimize() select_distinct= select_distinct && (const_tables != table_count); } - thd_proc_info(thd, "preparing"); + THD_STAGE_INFO(thd, stage_preparing); if (result->initialize_tables(this)) { DBUG_PRINT("error",("Error: initialize_tables() failed")); @@ -1785,7 +1780,7 @@ int JOIN::init_execution() if (need_tmp) { DBUG_PRINT("info",("Creating tmp table")); - thd_proc_info(thd, "Creating tmp table"); + THD_STAGE_INFO(thd, stage_copying_to_tmp_table); init_items_ref_array(); @@ -1830,7 +1825,7 @@ int JOIN::init_execution() if (group_list && simple_group) { DBUG_PRINT("info",("Sorting for group")); - thd_proc_info(thd, "Sorting for group"); + THD_STAGE_INFO(thd, stage_sorting_for_group); if (create_sort_index(thd, this, group_list, HA_POS_ERROR, HA_POS_ERROR, FALSE) || alloc_group_fields(this, group_list) || @@ -1853,7 +1848,7 @@ int JOIN::init_execution() if (!group_list && ! exec_tmp_table1->distinct && order && simple_order) { - thd_proc_info(thd, "Sorting for order"); + THD_STAGE_INFO(thd, stage_sorting_for_order); if (create_sort_index(thd, this, order, HA_POS_ERROR, HA_POS_ERROR, TRUE)) { @@ -2177,7 +2172,7 @@ JOIN::exec() int tmp_error; DBUG_ENTER("JOIN::exec"); - thd_proc_info(thd, "executing"); + THD_STAGE_INFO(thd, stage_executing); error= 0; if (procedure) { @@ -2185,7 +2180,8 @@ JOIN::exec() if (procedure->change_columns(procedure_fields_list) || result->prepare(procedure_fields_list, unit)) { - thd->limit_found_rows= thd->examined_row_count= 0; + thd->set_examined_row_count(0); + thd->limit_found_rows= 0; DBUG_VOID_RETURN; } columns_list= &procedure_fields_list; @@ -2226,7 +2222,7 @@ JOIN::exec() { error= (int) result->send_eof(); send_records= ((select_options & OPTION_FOUND_ROWS) ? 1 : - thd->sent_row_count); + thd->get_sent_row_count()); } } else @@ -2237,7 +2233,7 @@ JOIN::exec() } /* Single select (without union) always returns 0 or 1 row */ thd->limit_found_rows= send_records; - thd->examined_row_count= 0; + thd->set_examined_row_count(0); DBUG_VOID_RETURN; } /* @@ -2374,7 +2370,7 @@ JOIN::exec() curr_tmp_table= exec_tmp_table1; /* Copy data to the temporary table */ - thd_proc_info(thd, copy_to_tmp_table); + THD_STAGE_INFO(thd, stage_copying_to_tmp_table); DBUG_PRINT("info", ("%s", thd->proc_info)); if (!curr_join->sort_and_group && curr_join->const_tables != curr_join->table_count) @@ -2515,7 +2511,7 @@ JOIN::exec() } if (curr_join->group_list) { - thd_proc_info(thd, "Creating sort index"); + THD_STAGE_INFO(thd, stage_creating_sort_index); if (curr_join->join_tab == join_tab && save_join_tab()) { DBUG_VOID_RETURN; @@ -2529,7 +2525,7 @@ JOIN::exec() sortorder= curr_join->sortorder; } - thd_proc_info(thd, "Copying to group table"); + THD_STAGE_INFO(thd, stage_copying_to_group_table); DBUG_PRINT("info", ("%s", thd->proc_info)); if (curr_join != this) { @@ -2614,7 +2610,7 @@ JOIN::exec() if (curr_join->select_distinct && ! curr_join->group_list) { - thd_proc_info(thd, "Removing duplicates"); + THD_STAGE_INFO(thd, stage_removing_duplicates); if (remove_duplicates(curr_join, curr_tmp_table, *curr_fields_list, curr_join->tmp_having)) DBUG_VOID_RETURN; @@ -2685,7 +2681,7 @@ JOIN::exec() if (curr_join->group_list || curr_join->order) { DBUG_PRINT("info",("Sorting for send_result_set_metadata")); - thd_proc_info(thd, "Sorting result"); + THD_STAGE_INFO(thd, stage_sorting_result); /* If we have already done the group, add HAVING to sorted table */ if (curr_join->tmp_having && ! curr_join->group_list && ! curr_join->sort_and_group) @@ -2816,7 +2812,7 @@ JOIN::exec() curr_join->fields= curr_fields_list; curr_join->procedure= procedure; - thd_proc_info(thd, "Sending data"); + THD_STAGE_INFO(thd, stage_sending_data); DBUG_PRINT("info", ("%s", thd->proc_info)); result->send_result_set_metadata((procedure ? curr_join->procedure_fields_list : *curr_fields_list), @@ -2825,9 +2821,9 @@ JOIN::exec() thd->limit_found_rows= curr_join->send_records; /* Accumulate the counts from all join iterations of all join parts. */ - thd->examined_row_count+= curr_join->examined_rows; + thd->inc_examined_row_count(curr_join->examined_rows); DBUG_PRINT("counts", ("thd->examined_row_count: %lu", - (ulong) thd->examined_row_count)); + (ulong) thd->get_examined_row_count())); /* With EXPLAIN EXTENDED we have to restore original ref_array @@ -3017,7 +3013,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (!(join= new JOIN(thd, fields, select_options, result))) DBUG_RETURN(TRUE); - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); thd->lex->used_tables=0; if ((err= join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, @@ -3052,7 +3048,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, err: if (free_join) { - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); err|= select_lex->cleanup(); DBUG_RETURN(err || thd->is_error()); } @@ -10052,10 +10048,10 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) /* These init changes read_record */ if (tab->use_quick == 2) { - join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED; + join->thd->set_status_no_good_index_used(); tab->read_first_record= join_init_quick_read_record; if (statistics) - status_var_increment(join->thd->status_var.select_range_check_count); + join->thd->inc_status_select_range_check(); } else { @@ -10066,14 +10062,14 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) if (tab->select && tab->select->quick) { if (statistics) - status_var_increment(join->thd->status_var.select_range_count); + join->thd->inc_status_select_range(); } else { - join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; + join->thd->set_status_no_index_used(); if (statistics) { - status_var_increment(join->thd->status_var.select_scan_count); + join->thd->inc_status_select_scan(); join->thd->query_plan_flags|= QPLAN_FULL_SCAN; } } @@ -10083,16 +10079,14 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) if (tab->select && tab->select->quick) { if (statistics) - status_var_increment(join->thd->status_var. - select_full_range_join_count); + join->thd->inc_status_select_full_range_join(); } else { - join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; + join->thd->set_status_no_index_used(); if (statistics) { - status_var_increment(join->thd->status_var. - select_full_join_count); + join->thd->inc_status_select_full_join(); join->thd->query_plan_flags|= QPLAN_FULL_JOIN; } } @@ -11037,7 +11031,8 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables, result->send_eof(); // Should be safe } /* Update results for FOUND_ROWS */ - join->thd->limit_found_rows= join->thd->examined_row_count= 0; + join->thd->limit_found_rows= 0; + join->thd->set_examined_row_count(0); DBUG_RETURN(0); } @@ -14118,7 +14113,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, KEY *keyinfo; KEY_PART_INFO *key_part_info; Item **copy_func; - ENGINE_COLUMNDEF *recinfo; + TMP_ENGINE_COLUMNDEF *recinfo; /* total_uneven_bit_length is uneven bit length for visible fields hidden_uneven_bit_length is uneven bit length for hidden fields @@ -14133,7 +14128,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, (int) distinct, (int) save_sum_fields, (ulong) rows_limit,test(group))); - status_var_increment(thd->status_var.created_tmp_tables); + thd->inc_status_created_tmp_tables(); thd->query_plan_flags|= QPLAN_TMP_TABLE; if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) @@ -15077,8 +15072,7 @@ bool open_tmp_table(TABLE *table) } -#if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_ARIA_FOR_TMP_TABLES) - +#ifdef USE_ARIA_FOR_TMP_TABLES /* Create internal (MyISAM or Maria) temporary table @@ -15094,12 +15088,12 @@ bool open_tmp_table(TABLE *table) Create an internal emporary table according to passed description. The is assumed to have one unique index or constraint. - The passed array or ENGINE_COLUMNDEF structures must have this form: + The passed array or TMP_ENGINE_COLUMNDEF structures must have this form: 1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte when there are many nullable columns) 2. Table columns - 3. One free ENGINE_COLUMNDEF element (*recinfo points here) + 3. One free TMP_ENGINE_COLUMNDEF element (*recinfo points here) This function may use the free element to create hash column for unique constraint. @@ -15111,8 +15105,8 @@ bool open_tmp_table(TABLE *table) bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options, my_bool big_tables) { int error; @@ -15237,7 +15231,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, table->db_stat=0; goto err; } - status_var_increment(table->in_use->status_var.created_tmp_disk_tables); + table->in_use->inc_status_created_tmp_disk_tables(); table->in_use->query_plan_flags|= QPLAN_TMP_DISK; share->db_record_offset= 1; DBUG_RETURN(0); @@ -15245,20 +15239,6 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, DBUG_RETURN(1); } - -bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, - int error, - bool ignore_last_dupp_key_error) -{ - return create_internal_tmp_table_from_heap2(thd, table, - start_recinfo, recinfo, error, - ignore_last_dupp_key_error, - maria_hton, - "converting HEAP to Aria"); -} - #else /* @@ -15276,12 +15256,12 @@ bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, Create an internal emporary table according to passed description. The is assumed to have one unique index or constraint. - The passed array or ENGINE_COLUMNDEF structures must have this form: + The passed array or TMP_ENGINE_COLUMNDEF structures must have this form: 1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte when there are many nullable columns) 2. Table columns - 3. One free ENGINE_COLUMNDEF element (*recinfo points here) + 3. One free TMP_ENGINE_COLUMNDEF element (*recinfo points here) This function may use the free element to create hash column for unique constraint. @@ -15294,8 +15274,8 @@ bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, /* Create internal MyISAM temporary table */ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options, my_bool big_tables) { int error; @@ -15397,7 +15377,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, table->db_stat=0; goto err; } - status_var_increment(table->in_use->status_var.created_tmp_disk_tables); + table->in_use->inc_status_created_tmp_disk_tables(); table->in_use->query_plan_flags|= QPLAN_TMP_DISK; share->db_record_offset= 1; table->created= TRUE; @@ -15407,24 +15387,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, } -/** - If a HEAP table gets full, create a MyISAM table and copy all rows to this -*/ - -bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, - int error, - bool ignore_last_dupp_key_error) -{ - return create_internal_tmp_table_from_heap2(thd, table, - start_recinfo, recinfo, error, - ignore_last_dupp_key_error, - myisam_hton, - "converting HEAP to MyISAM"); -} - -#endif /* WITH_MARIA_STORAGE_ENGINE */ +#endif /* USE_ARIA_FOR_TMP_TABLES */ /* @@ -15433,20 +15396,18 @@ bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, */ -static bool -create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, - int error, - bool ignore_last_dupp_key_error, - handlerton *hton, - const char *proc_info) +bool +create_internal_tmp_table_from_heap(THD *thd, TABLE *table, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, + int error, + bool ignore_last_dupp_key_error) { TABLE new_table; TABLE_SHARE share; const char *save_proc_info; int write_err= 0; - DBUG_ENTER("create_internal_tmp_table_from_heap2"); + DBUG_ENTER("create_internal_tmp_table_from_heap"); if (table->s->db_type() != heap_hton || error != HA_ERR_RECORD_FILE_FULL) @@ -15461,13 +15422,13 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, new_table= *table; share= *table->s; new_table.s= &share; - new_table.s->db_plugin= ha_lock_engine(thd, hton); + new_table.s->db_plugin= ha_lock_engine(thd, TMP_ENGINE_HTON); if (!(new_table.file= get_new_handler(&share, &new_table.mem_root, new_table.s->db_type()))) DBUG_RETURN(1); // End of memory save_proc_info=thd->proc_info; - thd_proc_info(thd, proc_info); + THD_STAGE_INFO(thd, stage_converting_heap_to_myisam); new_table.no_rows= table->no_rows; if (create_internal_tmp_table(&new_table, table->key_info, start_recinfo, @@ -15534,8 +15495,8 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, table->file->change_table_ptr(table, table->s); table->use_all_columns(); if (save_proc_info) - thd_proc_info(thd, save_proc_info == copy_to_tmp_table ? - "Copying to tmp table on disk" : save_proc_info); + thd_proc_info(thd, (!strcmp(save_proc_info,"Copying to tmp table") ? + "Copying to tmp table on disk" : save_proc_info)); DBUG_RETURN(0); err: @@ -15563,7 +15524,7 @@ free_tmp_table(THD *thd, TABLE *entry) DBUG_PRINT("enter",("table: %s",entry->alias.c_ptr())); save_proc_info=thd->proc_info; - thd_proc_info(thd, "removing tmp table"); + THD_STAGE_INFO(thd, stage_removing_tmp_table); if (entry->file && entry->created) { diff --git a/sql/sql_select.h b/sql/sql_select.h index 289914df5c5..fa990d8a709 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -29,20 +29,11 @@ #endif #include "procedure.h" -#include <myisam.h> #include "sql_array.h" /* Array */ #include "records.h" /* READ_RECORD */ #include "opt_range.h" /* SQL_SELECT, QUICK_SELECT_I */ -#if defined(WITH_ARIA_STORAGE_ENGINE) -#include <maria.h> -#endif -#if defined(USE_ARIA_FOR_TMP_TABLES) -#define TMP_ENGINE_HTON maria_hton -#else -#define TMP_ENGINE_HTON myisam_hton -#endif /* Values in optimize */ #define KEY_OPTIMIZE_EXISTS 1 #define KEY_OPTIMIZE_REF_OR_NULL 2 @@ -1704,8 +1695,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, bool make_copy_field, uint convert_blob_length); bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options, my_bool big_tables); /* @@ -1769,12 +1760,12 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, const char* alias, bool do_not_open=FALSE); void free_tmp_table(THD *thd, TABLE *entry); bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, int error, bool ignore_last_dupp_key_error); bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, - ENGINE_COLUMNDEF *start_recinfo, - ENGINE_COLUMNDEF **recinfo, + TMP_ENGINE_COLUMNDEF *start_recinfo, + TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options, my_bool big_tables); bool open_tmp_table(TABLE *table); void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1e2ed90e1b7..903dc0d9cf2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1844,7 +1844,7 @@ static const char *thread_state_info(THD *tmp) { if (tmp->net.reading_or_writing == 2) return "Writing to net"; - else if (tmp->command == COM_SLEEP) + else if (tmp->get_command() == COM_SLEEP) return ""; else return "Reading from net"; @@ -1923,7 +1923,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) tmp_sctx->host ? tmp_sctx->host : ""); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); - thd_info->command=(int) tmp->command; + thd_info->command=(int) tmp->get_command(); mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var)) mysql_mutex_lock(&mysys_var->mutex); @@ -2061,8 +2061,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) "Killed" : 0)))) table->field[4]->store(val, strlen(val), cs); else - table->field[4]->store(command_name[tmp->command].str, - command_name[tmp->command].length, cs); + table->field[4]->store(command_name[tmp->get_command()].str, + command_name[tmp->get_command()].length, cs); /* MYSQL_TIME */ const ulonglong utime= (tmp->start_time ? (unow.val - tmp->start_time * HRTIME_RESOLUTION - @@ -6411,7 +6411,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) if (et.load_from_row(thd, event_table)) { - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias.c_ptr()); + my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event"); DBUG_RETURN(1); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 031932b4c06..8d73ce1388c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1471,6 +1471,7 @@ void execute_ddl_log_recovery() THD *thd; DDL_LOG_ENTRY ddl_log_entry; char file_name[FN_REFLEN]; + static char recover_query_string[]= "INTERNAL DDL LOG RECOVER IN PROGRESS"; DBUG_ENTER("execute_ddl_log_recovery"); /* @@ -1490,6 +1491,9 @@ void execute_ddl_log_recovery() thd->thread_stack= (char*) &thd; thd->store_globals(); + thd->set_query(recover_query_string, strlen(recover_query_string)); + + /* this also initialize LOCK_gdl */ num_entries= read_ddl_log_header(); for (i= 1; i < num_entries + 1; i++) { @@ -4337,7 +4341,7 @@ bool mysql_create_table_no_lock(THD *thd, } } - thd_proc_info(thd, "creating table"); + THD_STAGE_INFO(thd, stage_creating_table); #ifdef HAVE_READLINK { @@ -4453,7 +4457,7 @@ bool mysql_create_table_no_lock(THD *thd, error= FALSE; err: - thd_proc_info(thd, "After create"); + THD_STAGE_INFO(thd, stage_after_create); delete file; DBUG_RETURN(error); @@ -4642,6 +4646,20 @@ mysql_rename_table(handlerton *base, const char *old_db, my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE"); else if (error) my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error); + +#ifdef HAVE_PSI_TABLE_INTERFACE + /* + Remove the old table share from the pfs table share array. The new table + share will be created when the renamed table is first accessed. + */ + if (likely(error == 0)) + { + my_bool temp_table= (my_bool)is_prefix(old_name, tmp_file_prefix); + PSI_CALL(drop_table_share)(temp_table, old_db, strlen(old_db), + old_name, strlen(old_name)); + } +#endif + DBUG_RETURN(error != 0); } @@ -4834,7 +4852,7 @@ mysql_discard_or_import_tablespace(THD *thd, ALTER TABLE */ - thd_proc_info(thd, "discard_or_import_tablespace"); + THD_STAGE_INFO(thd, stage_discard_or_import_tablespace); discard= test(tablespace_op == DISCARD_TABLESPACE); @@ -4852,7 +4870,7 @@ mysql_discard_or_import_tablespace(THD *thd, error= table->file->ha_discard_or_import_tablespace(discard); - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); if (error) goto err; @@ -5954,7 +5972,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, to simplify further comparisions: we want to see if it's a RENAME later just by comparing the pointers, avoiding the need for strcmp. */ - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); table_name=table_list->table_name; alias= (lower_case_table_names == 2) ? table_list->alias : table_name; db=table_list->db; @@ -6148,7 +6166,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } - thd_proc_info(thd, "setup"); + THD_STAGE_INFO(thd, stage_setup); if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && !table->s->tmp_table) // no need to touch frm { @@ -6181,7 +6199,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (!error && (new_name != table_name || new_db != db)) { - thd_proc_info(thd, "rename"); + THD_STAGE_INFO(thd, stage_rename); /* Then do a 'simple' rename of the table. First we need to close all instances of 'source' table. @@ -6675,7 +6693,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (!table->s->tmp_table && need_lock_for_indexes && wait_while_table_is_used(thd, table, extra_func)) goto err_new_table_cleanup; - thd_proc_info(thd, "manage keys"); + THD_STAGE_INFO(thd, stage_manage_keys); DEBUG_SYNC(thd, "alter_table_manage_keys"); alter_table_manage_keys(table, table->file->indexes_are_disabled(), alter_info->keys_onoff); @@ -6866,7 +6884,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, (mysql_execute_command()) to release metadata locks. */ - thd_proc_info(thd, "rename result table"); + THD_STAGE_INFO(thd, stage_rename_result_table); my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix, current_pid, thd->thread_id); if (lower_case_table_names) @@ -7032,7 +7050,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (thd->locked_tables_list.reopen_tables(thd)) goto err_with_mdl; - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000);); DEBUG_SYNC(thd, "alter_table_before_main_binlog"); @@ -7278,7 +7296,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, tables.alias= tables.table_name= from->s->table_name.str; tables.db= from->s->db.str; - thd_proc_info(thd, "Sorting"); + THD_STAGE_INFO(thd, stage_sorting); if (thd->lex->select_lex.setup_ref_array(thd, order_num) || setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables, fields, all_fields, order) || @@ -7292,7 +7310,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, thd_progress_next_stage(thd); } - thd_proc_info(thd, "copy to tmp table"); + THD_STAGE_INFO(thd, stage_copy_to_tmp_table); /* Tell handler that we have values for all columns in the to table */ to->use_all_columns(); to->mark_virtual_columns_for_write(TRUE); @@ -7389,7 +7407,7 @@ err: free_io_cache(from); delete [] copy; - thd_proc_info(thd, "Enabling keys"); + THD_STAGE_INFO(thd, stage_enabling_keys); thd_progress_next_stage(thd); if (error > 0) diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 021267b53bd..df5f0c9d287 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -670,8 +670,8 @@ bool st_select_lex_unit::exec() 0); if (!saved_error) { - examined_rows+= thd->examined_row_count; - thd->examined_row_count= 0; + examined_rows+= thd->get_examined_row_count(); + thd->set_examined_row_count(0); if (union_result->flush()) { thd->lex->current_select= lex_select_save; @@ -813,7 +813,7 @@ bool st_select_lex_unit::exec() if (!saved_error) { thd->limit_found_rows = (ulonglong)table->file->stats.records + add_rows; - thd->examined_row_count+= examined_rows; + thd->inc_examined_row_count(examined_rows); } /* Mark for slow query log if any of the union parts didn't use diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f2b6c5c9f92..4b536c71fd6 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -301,7 +301,7 @@ int mysql_update(THD *thd, if (table_list->handle_derived(thd->lex, DT_PREPARE)) DBUG_RETURN(1); - thd_proc_info(thd, "init"); + THD_STAGE_INFO(thd, stage_init); table= table_list->table; if (!table_list->single_table_updatable()) @@ -429,7 +429,7 @@ int mysql_update(THD *thd, /* If running in safe sql mode, don't allow updates without keys */ if (table->quick_keys.is_clear_all()) { - thd->server_status|=SERVER_QUERY_NO_INDEX_USED; + thd->set_status_no_index_used(); if (safe_update && !using_limit) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, @@ -509,7 +509,7 @@ int mysql_update(THD *thd, { goto err; } - thd->examined_row_count+= examined_rows; + thd->inc_examined_row_count(examined_rows); /* Filesort has already found and selected the rows we want to update, so we don't need the where clause @@ -554,14 +554,14 @@ int mysql_update(THD *thd, else init_read_record_idx(&info, thd, table, 1, used_index, reverse); - thd_proc_info(thd, "Searching rows for update"); + THD_STAGE_INFO(thd, stage_searching_rows_for_update); ha_rows tmp_limit= limit; while (!(error=info.read_record(&info)) && !thd->killed) { if (table->vfield) update_virtual_fields(thd, table); - thd->examined_row_count++; + thd->inc_examined_row_count(1); if (!select || (error= select->skip_record(thd)) > 0) { if (table->file->was_semi_consistent_read()) @@ -637,7 +637,7 @@ int mysql_update(THD *thd, */ thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; - thd_proc_info(thd, "Updating"); + THD_STAGE_INFO(thd, stage_updating); transactional_table= table->file->has_transactions(); thd->abort_on_warning= test(!ignore && @@ -677,7 +677,7 @@ int mysql_update(THD *thd, { if (table->vfield) update_virtual_fields(thd, table); - thd->examined_row_count++; + thd->inc_examined_row_count(1); if (!select || select->skip_record(thd) > 0) { if (table->file->was_semi_consistent_read()) @@ -878,7 +878,7 @@ int mysql_update(THD *thd, end_read_record(&info); delete select; - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); (void) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); /* @@ -1446,7 +1446,7 @@ int multi_update::prepare(List<Item> ¬_used_values, thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; - thd_proc_info(thd, "updating main table"); + THD_STAGE_INFO(thd, stage_updating_main_table); tables_to_update= get_table_map(fields); @@ -2265,7 +2265,7 @@ bool multi_update::send_eof() ulonglong id; killed_state killed_status= NOT_KILLED; DBUG_ENTER("multi_update::send_eof"); - thd_proc_info(thd, "updating reference tables"); + THD_STAGE_INFO(thd, stage_updating_reference_tables); /* Does updates for the last n - 1 tables, returns 0 if ok; @@ -2279,7 +2279,7 @@ bool multi_update::send_eof() later carried out killing should not affect binlogging. */ killed_status= (local_error == 0) ? NOT_KILLED : thd->killed; - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); /* We must invalidate the query cache before binlog writing and ha_autocommit_... */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index bbc5c324573..02f70c12ad2 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -724,7 +724,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, DBUG_RETURN(0); err: - thd_proc_info(thd, "end"); + THD_STAGE_INFO(thd, stage_end); lex->link_first_table_back(view, link_to_local); unit->cleanup(); DBUG_RETURN(res || thd->is_error()); diff --git a/sql/table.cc b/sql/table.cc index cf9b3906cbd..4a66ab6f118 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3587,9 +3587,9 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) } else if (MYSQL_VERSION_ID == table->s->mysql_version) { - report_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, - ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), - table->alias.c_ptr(), + report_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2, + ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2), + table->s->db.str, table->s->table_name.str, table_def->count, table->s->fields); DBUG_RETURN(TRUE); } @@ -3835,7 +3835,7 @@ bool TABLE_SHARE::wait_for_old_version(THD *thd, struct timespec *abstime, mdl_context->find_deadlock(); wait_status= mdl_context->m_wait.timed_wait(thd, abstime, TRUE, - "Waiting for table flush"); + &stage_waiting_for_table_flush); mdl_context->done_waiting_for(); |