diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/opt_range.cc | 38 | ||||
-rw-r--r-- | sql/sql_class.cc | 48 | ||||
-rw-r--r-- | sql/sql_class.h | 40 | ||||
-rw-r--r-- | sql/sql_insert.cc | 1 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 9 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 16 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 7 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 8 | ||||
-rw-r--r-- | sql/wsrep_thd.cc | 21 |
10 files changed, 151 insertions, 39 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ec7b3dbbd7a..57bd244e738 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2434,6 +2434,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, KEY_PART *key_parts; KEY *key_info; PARAM param; + bool force_group_by = false; if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff)) DBUG_RETURN(0); // Fatal error flag is set @@ -2562,15 +2563,20 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, Try to construct a QUICK_GROUP_MIN_MAX_SELECT. Notice that it can be constructed no matter if there is a range tree. */ + DBUG_EXECUTE_IF("force_group_by", force_group_by = true; ); group_trp= get_best_group_min_max(¶m, tree, best_read_time); if (group_trp) { param.table->quick_condition_rows= MY_MIN(group_trp->records, head->stat_records()); - if (group_trp->read_cost < best_read_time) + if (group_trp->read_cost < best_read_time || force_group_by) { best_trp= group_trp; best_read_time= best_trp->read_cost; + if (force_group_by) + { + goto force_plan; + } } } @@ -2670,6 +2676,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, } } +force_plan: thd->mem_root= param.old_root; /* If we got a read plan, create a quick select from it. */ @@ -11534,13 +11541,28 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, DBUG_ASSERT(cur_prefix != NULL); result= file->ha_index_read_map(record, cur_prefix, keypart_map, HA_READ_AFTER_KEY); - if (result || last_range->max_keypart_map == 0) - DBUG_RETURN(result); - - key_range previous_endpoint; - last_range->make_max_endpoint(&previous_endpoint, prefix_length, keypart_map); - if (file->compare_key(&previous_endpoint) <= 0) - DBUG_RETURN(0); + if (result || last_range->max_keypart_map == 0) { + /* + Only return if actual failure occurred. For HA_ERR_KEY_NOT_FOUND + or HA_ERR_END_OF_FILE, we just want to continue to reach the next + set of ranges. It is possible for the storage engine to return + HA_ERR_KEY_NOT_FOUND/HA_ERR_END_OF_FILE even when there are more + keys if it respects the end range set by the read_range_first call + below. + */ + if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE) + DBUG_RETURN(result); + } else { + /* + For storage engines that don't respect end range, check if we've + moved past the current range. + */ + key_range previous_endpoint; + last_range->make_max_endpoint(&previous_endpoint, prefix_length, + keypart_map); + if (file->compare_key(&previous_endpoint) <= 0) + DBUG_RETURN(0); + } } uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0e6fe2a0c51..5c778d11c98 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4804,12 +4804,6 @@ extern "C" int thd_slave_thread(const MYSQL_THD thd) } -extern "C" int thd_rpl_stmt_based(const MYSQL_THD thd) -{ - return thd && - !thd->is_current_stmt_binlog_format_row() && - !thd->is_current_stmt_binlog_disabled(); -} /* Returns high resolution timestamp for the start @@ -6381,6 +6375,48 @@ int THD::decide_logging_format(TABLE_LIST *tables) DBUG_RETURN(0); } +int THD::decide_logging_format_low(TABLE *table) +{ + /* + INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys + can be unsafe. + */ + if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT && + !is_current_stmt_binlog_format_row() && + !lex->is_stmt_unsafe() && + lex->sql_command == SQLCOM_INSERT && + lex->duplicates == DUP_UPDATE) + { + uint unique_keys= 0; + uint keys= table->s->keys, i= 0; + Field *field; + for (KEY* keyinfo= table->s->key_info; + i < keys && unique_keys <= 1; i++, keyinfo++) + if (keyinfo->flags & HA_NOSAME && + !(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG && + //User given auto inc can be unsafe + !keyinfo->key_part->field->val_int())) + { + for (uint j= 0; j < keyinfo->user_defined_key_parts; j++) + { + field= keyinfo->key_part[j].field; + if(!bitmap_is_set(table->write_set,field->field_index)) + goto exit; + } + unique_keys++; +exit:; + } + + if (unique_keys > 1) + { + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); + binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags(); + set_current_stmt_binlog_format_row_if_mixed(); + return 1; + } + } + return 0; +} /* Implementation of interface to write rows to the binary log through the diff --git a/sql/sql_class.h b/sql/sql_class.h index acf699f72e3..e5de03d4911 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2452,6 +2452,20 @@ public: /* container for handler's private per-connection data */ Ha_data ha_data[MAX_HA]; + /** + Bit field for the state of binlog warnings. + + The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of + unsafeness that the current statement has. + + This must be a member of THD and not of LEX, because warnings are + detected and issued in different places (@c + decide_logging_format() and @c binlog_query(), respectively). + Between these calls, the THD->lex object may change; e.g., if a + stored routine is invoked. Only THD persists between the calls. + */ + uint32 binlog_unsafe_warning_flags; + #ifndef MYSQL_CLIENT binlog_cache_mngr * binlog_setup_trx_data(); @@ -2561,20 +2575,6 @@ private: */ enum_binlog_format current_stmt_binlog_format; - /** - Bit field for the state of binlog warnings. - - The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of - unsafeness that the current statement has. - - This must be a member of THD and not of LEX, because warnings are - detected and issued in different places (@c - decide_logging_format() and @c binlog_query(), respectively). - Between these calls, the THD->lex object may change; e.g., if a - stored routine is invoked. Only THD persists between the calls. - */ - uint32 binlog_unsafe_warning_flags; - /* Number of outstanding table maps, i.e., table maps in the transaction cache. @@ -4455,6 +4455,18 @@ public: } void leave_locked_tables_mode(); int decide_logging_format(TABLE_LIST *tables); + /* + In Some cases when decide_logging_format is called it does not have all + information to decide the logging format. So that cases we call decide_logging_format_2 + at later stages in execution. + One example would be binlog format for IODKU but column with unique key is not inserted. + We dont have inserted columns info when we call decide_logging_format so on later stage we call + decide_logging_format_low + + @returns 0 if no format is changed + 1 if there is change in binlog format + */ + int decide_logging_format_low(TABLE *table); enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE}; void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 29be1c4c645..709f3ad87a0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1057,6 +1057,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, break; } + thd->decide_logging_format_low(table); #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3e1844a7f4a..9bd2e6040f0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6072,7 +6072,7 @@ finish: trans_rollback_stmt(thd); } #ifdef WITH_WSREP - if (thd->spcont && + else if (thd->spcont && (thd->wsrep_conflict_state == MUST_ABORT || thd->wsrep_conflict_state == ABORTED || thd->wsrep_conflict_state == CERT_FAILURE)) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index eb623e14912..182254cfe60 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5219,7 +5219,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, err: /* In RBR we don't need to log CREATE TEMPORARY TABLE */ - if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) + if (!result && thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) DBUG_RETURN(result); if (create_info->tmp_table()) @@ -10131,6 +10131,7 @@ end_temporary: (ulong) (copied + deleted), (ulong) deleted, (ulong) thd->get_stmt_da()->current_statement_warn_count()); my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_buff); + DEBUG_SYNC(thd, "alter_table_inplace_trans_commit"); DBUG_RETURN(false); err_new_table_cleanup: @@ -10232,12 +10233,14 @@ bool mysql_trans_commit_alter_copy_data(THD *thd) uint save_unsafe_rollback_flags; DBUG_ENTER("mysql_trans_commit_alter_copy_data"); - /* Save flags as transcommit_implicit_are_deleting_them */ + /* Save flags as trans_commit_implicit are deleting them */ save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags; + DEBUG_SYNC(thd, "alter_table_copy_trans_commit"); + if (ha_enable_transaction(thd, TRUE)) DBUG_RETURN(TRUE); - + /* Ensure that the new table is saved properly to disk before installing the new .frm. diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 21e2e5bd93f..28a9ddb0bea 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -183,7 +183,19 @@ static PSI_file_info wsrep_files[]= { { &key_file_wsrep_gra_log, "wsrep_gra_log", 0} }; -#endif + +PSI_thread_key key_wsrep_sst_joiner, key_wsrep_sst_donor, + key_wsrep_rollbacker, key_wsrep_applier; + +static PSI_thread_info wsrep_threads[]= +{ + {&key_wsrep_sst_joiner, "wsrep_sst_joiner_thread", PSI_FLAG_GLOBAL}, + {&key_wsrep_sst_donor, "wsrep_sst_donor_thread", PSI_FLAG_GLOBAL}, + {&key_wsrep_rollbacker, "wsrep_rollbacker_thread", PSI_FLAG_GLOBAL}, + {&key_wsrep_applier, "wsrep_applier_thread", PSI_FLAG_GLOBAL} +}; + +#endif /* HAVE_PSI_INTERFACE */ my_bool wsrep_inited = 0; // initialized ? @@ -799,6 +811,7 @@ void wsrep_thr_init() mysql_mutex_register("sql", wsrep_mutexes, array_elements(wsrep_mutexes)); mysql_cond_register("sql", wsrep_conds, array_elements(wsrep_conds)); mysql_file_register("sql", wsrep_files, array_elements(wsrep_files)); + mysql_thread_register("sql", wsrep_threads, array_elements(wsrep_threads)); #endif mysql_mutex_init(key_LOCK_wsrep_ready, &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); @@ -814,6 +827,7 @@ void wsrep_thr_init() mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST); + DBUG_VOID_RETURN; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 592d2f279f4..395dabb39be 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -286,7 +286,14 @@ extern PSI_mutex_key key_LOCK_wsrep_slave_threads; extern PSI_mutex_key key_LOCK_wsrep_desync; extern PSI_file_key key_file_wsrep_gra_log; + +extern PSI_thread_key key_wsrep_sst_joiner; +extern PSI_thread_key key_wsrep_sst_donor; +extern PSI_thread_key key_wsrep_rollbacker; +extern PSI_thread_key key_wsrep_applier; #endif /* HAVE_PSI_INTERFACE */ + + struct TABLE_LIST; class Alter_info; int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 318714dd29c..5c3e5642cda 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -729,10 +729,10 @@ static ssize_t sst_prepare_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str(), env()); mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg); + ret = mysql_thread_create (key_wsrep_sst_joiner, &tmp, NULL, sst_joiner_thread, &arg); if (ret) { - WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)", + WSREP_ERROR("sst_prepare_other(): mysql_thread_create() failed: %d (%s)", ret, strerror(ret)); return -ret; } @@ -1381,10 +1381,10 @@ static int sst_donate_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str(), env); mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg); + ret = mysql_thread_create (key_wsrep_sst_donor, &tmp, NULL, sst_donor_thread, &arg); if (ret) { - WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)", + WSREP_ERROR("sst_donate_other(): mysql_thread_create() failed: %d (%s)", ret, strerror(ret)); return ret; } diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 34b39c6d1e3..a45828beab3 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -417,9 +417,26 @@ static void wsrep_replication_process(THD *thd) static bool create_wsrep_THD(wsrep_thread_args* args) { - ulong old_wsrep_running_threads= wsrep_running_threads; mysql_mutex_lock(&LOCK_thread_count); - bool res= pthread_create(&args->thread_id, &connection_attrib, start_wsrep_THD, + ulong old_wsrep_running_threads= wsrep_running_threads; +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_thread_key key; + + switch (args->thread_type) + { + case WSREP_APPLIER_THREAD: + key= key_wsrep_applier; + break; + case WSREP_ROLLBACKER_THREAD: + key= key_wsrep_rollbacker; + break; + default: + assert(0); + break; + } +#endif + + bool res= mysql_thread_create(key, &args->thread_id, &connection_attrib, start_wsrep_THD, (void*)args); /* if starting a thread on server startup, wait until the this thread's THD |