summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_range.cc38
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h40
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_table.cc9
-rw-r--r--sql/wsrep_mysqld.cc16
-rw-r--r--sql/wsrep_mysqld.h7
-rw-r--r--sql/wsrep_sst.cc8
-rw-r--r--sql/wsrep_thd.cc21
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(&param, 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