diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/event_scheduler.cc | 80 | ||||
-rw-r--r-- | sql/event_scheduler.h | 2 | ||||
-rw-r--r-- | sql/events.cc | 7 | ||||
-rw-r--r-- | sql/events.h | 2 | ||||
-rw-r--r-- | sql/ha_partition.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 68 | ||||
-rw-r--r-- | sql/rpl_utility.cc | 20 | ||||
-rw-r--r-- | sql/slave.cc | 6 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 10 | ||||
-rw-r--r-- | sql/sql_manager.cc | 9 | ||||
-rw-r--r-- | sql/sql_show.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 27 | ||||
-rw-r--r-- | sql/sys_vars.cc | 8 |
14 files changed, 168 insertions, 84 deletions
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index f1c684add2b..3fb80203338 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -241,6 +241,12 @@ event_scheduler_thread(void *arg) my_free(arg); if (!res) scheduler->run(thd); + else + { + thd->proc_info= "Clearing"; + net_end(&thd->net); + delete thd; + } DBUG_LEAVE; // Against gcc warnings my_thread_end(); @@ -360,26 +366,26 @@ Event_scheduler::~Event_scheduler() } -/* +/** Starts the scheduler (again). Creates a new THD and passes it to a forked thread. Does not wait for acknowledgement from the new thread that it has started. Asynchronous starting. Most of the needed initializations are done in the current thread to minimize the chance of failure in the spawned thread. - SYNOPSIS - Event_scheduler::start() + @param[out] err_no - errno indicating type of error which caused + failure to start scheduler thread. - RETURN VALUE - FALSE OK - TRUE Error (not reported) + @return + @retval false Success. + @retval true Error. */ bool -Event_scheduler::start() +Event_scheduler::start(int *err_no) { THD *new_thd= NULL; - bool ret= FALSE; + bool ret= false; pthread_t th; struct scheduler_param *scheduler_param_value; DBUG_ENTER("Event_scheduler::start"); @@ -389,10 +395,16 @@ Event_scheduler::start() if (state > INITIALIZED) goto end; + DBUG_EXECUTE_IF("event_scheduler_thread_create_failure", { + *err_no= 11; + Events::opt_event_scheduler= Events::EVENTS_OFF; + ret= true; + goto end; }); + if (!(new_thd= new THD)) { sql_print_error("Event Scheduler: Cannot initialize the scheduler thread"); - ret= TRUE; + ret= true; goto end; } pre_init_event_thread(new_thd); @@ -415,28 +427,30 @@ Event_scheduler::start() DBUG_PRINT("info", ("Setting state go RUNNING")); state= RUNNING; DBUG_PRINT("info", ("Forking new thread for scheduler. THD: 0x%lx", (long) new_thd)); - if (mysql_thread_create(key_thread_event_scheduler, - &th, &connection_attrib, event_scheduler_thread, - (void*)scheduler_param_value)) + if ((*err_no= mysql_thread_create(key_thread_event_scheduler, + &th, &connection_attrib, + event_scheduler_thread, + (void*)scheduler_param_value))) { DBUG_PRINT("error", ("cannot create a new thread")); - state= INITIALIZED; - scheduler_thd= NULL; - ret= TRUE; + sql_print_error("Event scheduler: Failed to start scheduler," + " Can not create thread for event scheduler (errno=%d)", + *err_no); new_thd->proc_info= "Clearing"; DBUG_ASSERT(new_thd->net.buff != 0); net_end(&new_thd->net); - mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - dec_thread_running(); + + state= INITIALIZED; + scheduler_thd= NULL; delete new_thd; - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + + delete scheduler_param_value; + ret= true; } + end: UNLOCK_DATA(); - DBUG_RETURN(ret); } @@ -547,7 +561,20 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) if ((res= mysql_thread_create(key_thread_event_worker, &th, &connection_attrib, event_worker_thread, event_name))) + { + mysql_mutex_lock(&LOCK_global_system_variables); + Events::opt_event_scheduler= Events::EVENTS_OFF; + mysql_mutex_unlock(&LOCK_global_system_variables); + + sql_print_error("Event_scheduler::execute_top: Can not create event worker" + " thread (errno=%d). Stopping event scheduler", res); + + new_thd->proc_info= "Clearing"; + DBUG_ASSERT(new_thd->net.buff != 0); + net_end(&new_thd->net); + goto error; + } ++started_events; @@ -557,17 +584,8 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) error: DBUG_PRINT("error", ("Event_scheduler::execute_top() res: %d", res)); if (new_thd) - { - new_thd->proc_info= "Clearing"; - DBUG_ASSERT(new_thd->net.buff != 0); - net_end(&new_thd->net); - mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - dec_thread_running(); delete new_thd; - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - } + delete event_name; DBUG_RETURN(TRUE); } diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index aca4b74dd95..9435ee548d9 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -78,7 +78,7 @@ public: /* State changing methods follow */ bool - start(); + start(int *err_no); bool stop(); diff --git a/sql/events.cc b/sql/events.cc index 2cedb007462..8ef90fdb622 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -798,6 +798,7 @@ Events::init(my_bool opt_noacl_or_bootstrap) { THD *thd; + int err_no; bool res= FALSE; DBUG_ENTER("Events::init"); @@ -869,7 +870,7 @@ Events::init(my_bool opt_noacl_or_bootstrap) } if (event_queue->init_queue(thd) || load_events_from_db(thd) || - (opt_event_scheduler == EVENTS_ON && scheduler->start())) + (opt_event_scheduler == EVENTS_ON && scheduler->start(&err_no))) { sql_print_error("Event Scheduler: Error while loading from disk."); res= TRUE; /* fatal error: request unireg_abort */ @@ -1017,9 +1018,9 @@ Events::dump_internal_status() DBUG_VOID_RETURN; } -bool Events::start() +bool Events::start(int *err_no) { - return scheduler->start(); + return scheduler->start(err_no); } bool Events::stop() diff --git a/sql/events.h b/sql/events.h index a337b29049a..f176a81ea9d 100644 --- a/sql/events.h +++ b/sql/events.h @@ -79,7 +79,7 @@ public: /* Protected using LOCK_global_system_variables only. */ static ulong opt_event_scheduler; static bool check_if_system_tables_error(); - static bool start(); + static bool start(int *err_no); static bool stop(); public: diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 17f02c24422..c3f2af27282 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5887,7 +5887,7 @@ void ha_partition::get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id) { handler *file= m_file[part_id]; - file->info(HA_STATUS_CONST | HA_STATUS_TIME | HA_STATUS_VARIABLE | + file->info(HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_VARIABLE_EXTRA | HA_STATUS_NO_LOCK); stat_info->records= file->stats.records; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c97a8c542d6..287ca3e4aa4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1258,11 +1258,12 @@ void kill_mysql(void) if (!kill_in_progress) { pthread_t tmp; + int error; abort_loop=1; - if (mysql_thread_create(0, /* Not instrumented */ - &tmp, &connection_attrib, kill_server_thread, - (void*) 0)) - sql_print_error("Can't create thread to kill server"); + if ((error= mysql_thread_create(0, /* Not instrumented */ + &tmp, &connection_attrib, + kill_server_thread, (void*) 0))) + sql_print_error("Can't create thread to kill server (errno= %d).", error); } #endif DBUG_VOID_RETURN; @@ -2728,10 +2729,12 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) #endif #ifdef USE_ONE_SIGNAL_HAND pthread_t tmp; - if (mysql_thread_create(0, /* Not instrumented */ - &tmp, &connection_attrib, kill_server_thread, - (void*) &sig)) - sql_print_error("Can't create thread to kill server"); + if ((error= mysql_thread_create(0, /* Not instrumented */ + &tmp, &connection_attrib, + kill_server_thread, + (void*) &sig))) + sql_print_error("Can't create thread to kill server (errno= %d)", + error); #else kill_server((void*) sig); // MIT THREAD has a alarm thread #endif @@ -4116,9 +4119,12 @@ static void create_shutdown_thread() #ifdef __WIN__ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name); pthread_t hThread; - if (mysql_thread_create(key_thread_handle_shutdown, - &hThread, &connection_attrib, handle_shutdown, 0)) - sql_print_warning("Can't create thread to handle shutdown requests"); + int error; + if ((error= mysql_thread_create(key_thread_handle_shutdown, + &hThread, &connection_attrib, + handle_shutdown, 0))) + sql_print_warning("Can't create thread to handle shutdown requests" + " (errno= %d)", error); // On "Stop Service" we have to do regular shutdown Service.SetShutdownEvent(hEventShutdown); @@ -4132,6 +4138,7 @@ static void create_shutdown_thread() static void handle_connections_methods() { pthread_t hThread; + int error; DBUG_ENTER("handle_connections_methods"); if (hPipe == INVALID_HANDLE_VALUE && (!have_tcpip || opt_disable_networking) && @@ -4147,22 +4154,24 @@ static void handle_connections_methods() if (hPipe != INVALID_HANDLE_VALUE) { handler_count++; - if (mysql_thread_create(key_thread_handle_con_namedpipes, - &hThread, &connection_attrib, - handle_connections_namedpipes, 0)) + if ((error= mysql_thread_create(key_thread_handle_con_namedpipes, + &hThread, &connection_attrib, + handle_connections_namedpipes, 0))) { - sql_print_warning("Can't create thread to handle named pipes"); + sql_print_warning("Can't create thread to handle named pipes" + " (errno= %d)", error); handler_count--; } } if (have_tcpip && !opt_disable_networking) { handler_count++; - if (mysql_thread_create(key_thread_handle_con_sockets, - &hThread, &connection_attrib, - handle_connections_sockets_thread, 0)) + if ((error= mysql_thread_create(key_thread_handle_con_sockets, + &hThread, &connection_attrib, + handle_connections_sockets_thread, 0))) { - sql_print_warning("Can't create thread to handle TCP/IP"); + sql_print_warning("Can't create thread to handle TCP/IP", + " (errno= %d)", error); handler_count--; } } @@ -4170,11 +4179,12 @@ static void handle_connections_methods() if (opt_enable_shared_memory) { handler_count++; - if (mysql_thread_create(key_thread_handle_con_sharedmem, - &hThread, &connection_attrib, - handle_connections_shared_memory, 0)) + if ((error= mysql_thread_create(key_thread_handle_con_sharedmem, + &hThread, &connection_attrib, + handle_connections_shared_memory, 0))) { - sql_print_warning("Can't create thread to handle shared memory"); + sql_print_warning("Can't create thread to handle shared memory", + " (errno= %d)", error); handler_count--; } } @@ -4909,11 +4919,14 @@ static void bootstrap(MYSQL_FILE *file) bootstrap_file=file; #ifndef EMBEDDED_LIBRARY // TODO: Enable this - if (mysql_thread_create(key_thread_bootstrap, - &thd->real_id, &connection_attrib, handle_bootstrap, - (void*) thd)) + int error; + if ((error= mysql_thread_create(key_thread_bootstrap, + &thd->real_id, &connection_attrib, + handle_bootstrap, + (void*) thd))) { - sql_print_warning("Can't create thread to handle bootstrap"); + sql_print_warning("Can't create thread to handle bootstrap (errno= %d)", + error); bootstrap_error=-1; DBUG_VOID_RETURN; } @@ -5012,6 +5025,7 @@ void create_thread_to_handle_connection(THD *thd) DBUG_PRINT("error", ("Can't create thread to handle request (error %d)", error)); + thread_count--; thd->killed= THD::KILL_CONNECTION; // Safety mysql_mutex_unlock(&LOCK_thread_count); diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 2643f2d6059..1527676ee58 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2013, 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 @@ -878,6 +878,7 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE * DBUG_ENTER("table_def::create_conversion_table"); List<Create_field> field_list; + TABLE *conv_table= NULL; /* At slave, columns may differ. So we should create min(columns@master, columns@slave) columns in the @@ -919,10 +920,15 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE * break; case MYSQL_TYPE_DECIMAL: - precision= field_metadata(col); - decimals= static_cast<Field_num*>(target_table->field[col])->dec; - max_length= field_metadata(col); - break; + sql_print_error("In RBR mode, Slave received incompatible DECIMAL field " + "(old-style decimal field) from Master while creating " + "conversion table. Please consider changing datatype on " + "Master to new style decimal by executing ALTER command for" + " column Name: %s.%s.%s.", + target_table->s->db.str, + target_table->s->table_name.str, + target_table->field[col]->field_name); + goto err; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -950,7 +956,9 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE * field_def->interval= interval; } - TABLE *conv_table= create_virtual_tmp_table(thd, field_list); + conv_table= create_virtual_tmp_table(thd, field_list); + +err: if (conv_table == NULL) rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, ER(ER_SLAVE_CANT_CREATE_CONVERSION), diff --git a/sql/slave.cc b/sql/slave.cc index 7fbe206c8a3..6e7c80e5803 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -709,6 +709,7 @@ int start_slave_thread( { pthread_t th; ulong start_id; + int error; DBUG_ENTER("start_slave_thread"); DBUG_ASSERT(mi->inited); @@ -735,9 +736,10 @@ int start_slave_thread( } start_id= *slave_run_id; DBUG_PRINT("info",("Creating new slave thread")); - if (mysql_thread_create(thread_key, - &th, &connection_attrib, h_func, (void*)mi)) + if ((error = mysql_thread_create(thread_key, + &th, &connection_attrib, h_func, (void*)mi))) { + sql_print_error("Can't create slave thread (errno= %d).", error); if (start_lock) mysql_mutex_unlock(start_lock); DBUG_RETURN(ER_SLAVE_THREAD); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 03b8cff3e25..94a6baf9f92 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -781,6 +781,7 @@ THD::THD() /* statement id */ 0), rli_fake(0), rli_slave(NULL), user_time(0), in_sub_stmt(0), + fill_status_recursion_level(0), binlog_unsafe_warning_flags(0), binlog_table_maps(0), table_map_for_update(0), diff --git a/sql/sql_class.h b/sql/sql_class.h index 093758ce389..64c05fe87c9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1586,6 +1586,16 @@ public: /* <> 0 if we are inside of trigger or stored function. */ uint in_sub_stmt; + /** + Used by fill_status() to avoid acquiring LOCK_status mutex twice + when this function is called recursively (e.g. queries + that contains SELECT on I_S.GLOBAL_STATUS with subquery on the + same I_S table). + Incremented each time fill_status() function is entered and + decremented each time before it returns from the function. + */ + uint fill_status_recursion_level; + /* container for handler's private per-connection data */ Ha_data ha_data[MAX_HA]; diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 221ba56130a..74a670346e0 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -136,9 +136,12 @@ void start_handle_manager() if (flush_time && flush_time != ~(ulong) 0L) { pthread_t hThread; - if (mysql_thread_create(key_thread_handle_manager, - &hThread, &connection_attrib, handle_manager, 0)) - sql_print_warning("Can't create handle_manager thread"); + int error; + if ((error= mysql_thread_create(key_thread_handle_manager, + &hThread, &connection_attrib, + handle_manager, 0))) + sql_print_warning("Can't create handle_manager thread (errno= %d)", + error); } DBUG_VOID_RETURN; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2811483a0b1..fbd163f4667 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6215,14 +6215,20 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) tmp1= &thd->status_var; } - mysql_mutex_lock(&LOCK_status); + /* + Avoid recursive acquisition of LOCK_status in cases when WHERE clause + represented by "cond" contains subquery on I_S.SESSION/GLOBAL_STATUS. + */ + if (thd->fill_status_recursion_level++ == 0) + mysql_mutex_lock(&LOCK_status); if (option_type == OPT_GLOBAL) calc_sum_of_all_status(&tmp); res= show_status_array(thd, wild, (SHOW_VAR *)all_status_vars.buffer, option_type, tmp1, "", tables->table, upper_case_names, cond); - mysql_mutex_unlock(&LOCK_status); + if (thd->fill_status_recursion_level-- == 1) + mysql_mutex_unlock(&LOCK_status); DBUG_RETURN(res); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c31ba5bb259..ac121572ab2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2001,6 +2001,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, bool non_tmp_error= 0; bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0; bool non_tmp_table_deleted= 0; + bool is_drop_tmp_if_exists_added= 0; String built_query; String built_trans_tmp_query, built_non_trans_tmp_query; DBUG_ENTER("mysql_rm_table_no_locks"); @@ -2029,6 +2030,15 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, table stems from the fact that such drop does not commit an ongoing transaction and changes to non-transactional tables must be written ahead of the transaction in some circumstances. + + 6- Slave SQL thread ignores all replicate-* filter rules + for temporary tables with 'IF EXISTS' clause. (See sql/sql_parse.cc: + mysql_execute_command() for details). These commands will be binlogged + as they are, even if the default database (from USE `db`) is not present + on the Slave. This can cause point in time recovery failures later + when user uses the slave's binlog to re-apply. Hence at the time of binary + logging, these commands will be written with fully qualified table names + and use `db` will be suppressed. */ if (!dont_log_query) { @@ -2043,6 +2053,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, if (thd->is_current_stmt_binlog_format_row() || if_exists) { + is_drop_tmp_if_exists_added= true; built_trans_tmp_query.set_charset(system_charset_info); built_trans_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS "); built_non_trans_tmp_query.set_charset(system_charset_info); @@ -2120,10 +2131,12 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, String *built_ptr_query= (is_trans ? &built_trans_tmp_query : &built_non_trans_tmp_query); /* - Don't write the database name if it is the current one (or if - thd->db is NULL). + Write the database name if it is not the current one or if + thd->db is NULL or 'IF EXISTS' clause is present in 'DROP TEMPORARY' + query. */ - if (thd->db == NULL || strcmp(db,thd->db) != 0) + if (thd->db == NULL || strcmp(db,thd->db) != 0 + || is_drop_tmp_if_exists_added ) { append_identifier(thd, built_ptr_query, db, db_len); built_ptr_query->append("."); @@ -2317,7 +2330,9 @@ err: error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_non_trans_tmp_query.ptr(), built_non_trans_tmp_query.length(), - FALSE, FALSE, FALSE, 0); + FALSE, FALSE, + is_drop_tmp_if_exists_added, + 0); } if (trans_tmp_table_deleted) { @@ -2327,7 +2342,9 @@ err: error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_trans_tmp_query.ptr(), built_trans_tmp_query.length(), - TRUE, FALSE, FALSE, 0); + TRUE, FALSE, + is_drop_tmp_if_exists_added, + 0); } if (non_tmp_table_deleted) { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 2430a54ffd7..1d0f9691629 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -746,6 +746,7 @@ static bool event_scheduler_check(sys_var *self, THD *thd, set_var *var) } static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) { + int err_no= 0; uint opt_event_scheduler_value= Events::opt_event_scheduler; mysql_mutex_unlock(&LOCK_global_system_variables); /* @@ -765,11 +766,14 @@ static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) for deadlocks. See bug#51160. */ bool ret= opt_event_scheduler_value == Events::EVENTS_ON - ? Events::start() + ? Events::start(&err_no) : Events::stop(); mysql_mutex_lock(&LOCK_global_system_variables); if (ret) - my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), 0); + { + Events::opt_event_scheduler= Events::EVENTS_OFF; + my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), err_no); + } return ret; } |