summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-11-06 08:41:48 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-11-06 08:41:48 +0200
commit32062cc61cd00e4cd3b7939c8a09f9c3ac34ec76 (patch)
tree098d64b7c988bab8cca25b0f716d92f6f7e72ed9 /sql
parentaf9649c722810eb1754953eb406a84ec876ce693 (diff)
parentbae21bfb5de17328c33c3da8d191c6d3af14ae02 (diff)
downloadmariadb-git-32062cc61cd00e4cd3b7939c8a09f9c3ac34ec76.tar.gz
Merge 10.1 into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/compat56.cc3
-rw-r--r--sql/events.cc16
-rw-r--r--sql/field_conv.cc2
-rw-r--r--sql/ha_partition.cc9
-rw-r--r--sql/ha_partition.h1
-rw-r--r--sql/item_cmpfunc.cc15
-rw-r--r--sql/lock.cc16
-rw-r--r--sql/lock.h1
-rw-r--r--sql/log_event.cc55
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/opt_range.cc6
-rw-r--r--sql/rpl_gtid.cc76
-rw-r--r--sql/rpl_gtid.h2
-rw-r--r--sql/rpl_rli.cc79
-rw-r--r--sql/rpl_rli.h11
-rw-r--r--sql/sql_acl.cc4
-rw-r--r--sql/sql_admin.cc3
-rw-r--r--sql/sql_alter.cc11
-rw-r--r--sql/sql_alter.h2
-rw-r--r--sql/sql_base.cc79
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_partition_admin.cc4
-rw-r--r--sql/sql_plugin.cc10
-rw-r--r--sql/sql_trigger.cc5
-rw-r--r--sql/sql_view.cc9
-rw-r--r--sql/sql_yacc.yy13
-rw-r--r--sql/wsrep_mysqld.cc2
31 files changed, 273 insertions, 182 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 4d6214e1c32..c1f1df818ed 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -319,7 +319,7 @@ DTRACE_INSTRUMENT_STATIC_LIBS(mysqld
SET(WITH_MYSQLD_LDFLAGS "" CACHE STRING "Additional linker flags for mysqld")
MARK_AS_ADVANCED(WITH_MYSQLD_LDFLAGS)
IF(WITH_MYSQLD_LDFLAGS)
- GET_TARGET_PROPERTY(mysqld LINK_FLAGS MYSQLD_LINK_FLAGS)
+ GET_TARGET_PROPERTY(MYSQLD_LINK_FLAGS mysqld LINK_FLAGS)
IF(NOT MYSQLD_LINK_FLAGS)
SET(MYSQLD_LINK_FLAGS)
ENDIF()
diff --git a/sql/compat56.cc b/sql/compat56.cc
index 704d1db9a98..b2e67a50491 100644
--- a/sql/compat56.cc
+++ b/sql/compat56.cc
@@ -252,6 +252,9 @@ void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong tmp)
{
longlong ymd, hms;
longlong ymdhms, ym;
+
+ DBUG_ASSERT(tmp != LONGLONG_MIN);
+
if ((ltime->neg= (tmp < 0)))
tmp= -tmp;
diff --git a/sql/events.cc b/sql/events.cc
index e914dba1009..cd0257f5317 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -418,10 +418,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
-#ifdef WITH_WSREP
- error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
+
}
@@ -549,10 +549,9 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
-#ifdef WITH_WSREP
-error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
}
@@ -616,10 +615,9 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
-#ifdef WITH_WSREP
-error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
}
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 48c448aa57f..cec3d3a3e7d 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2016, MariaDB
+ Copyright (c) 2010, 2018, MariaDB Corporation
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
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index c05f55e457d..090102266f0 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -3895,9 +3895,14 @@ THR_LOCK_DATA **ha_partition::store_lock(THD *thd,
}
else
{
- for (i= bitmap_get_first_set(&(m_part_info->lock_partitions));
+ MY_BITMAP *used_partitions= lock_type == TL_UNLOCK ||
+ lock_type == TL_IGNORE ?
+ &m_locked_partitions :
+ &m_part_info->lock_partitions;
+
+ for (i= bitmap_get_first_set(used_partitions);
i < m_tot_parts;
- i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
+ i= bitmap_get_next_set(used_partitions, i))
{
DBUG_PRINT("info", ("store lock %d iteration", i));
to= m_file[i]->store_lock(thd, to, lock_type);
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 286c6961531..e348da08443 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -244,7 +244,6 @@ private:
/*
Variables for lock structures.
*/
- THR_LOCK_DATA lock; /* MySQL lock */
bool auto_increment_lock; /**< lock reading/updating auto_inc */
/**
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 69ebeb2b95c..57f258be741 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4310,11 +4310,20 @@ bool Item_func_in::fix_length_and_dec()
if (field_item->field_type() == MYSQL_TYPE_LONGLONG ||
field_item->field_type() == MYSQL_TYPE_YEAR)
{
- bool all_converted= TRUE;
+ bool all_converted= true;
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- if (!convert_const_to_int(thd, field_item, &arg[0]))
- all_converted= FALSE;
+ /*
+ Explicit NULLs should not affect data cmp_type resolution:
+ - we ignore NULLs when calling collect_cmp_type()
+ - we ignore NULLs here
+ So this expression:
+ year_column IN (DATE'2001-01-01', NULL)
+ switches from TIME_RESULT to INT_RESULT.
+ */
+ if (arg[0]->type() != Item::NULL_ITEM &&
+ !convert_const_to_int(thd, field_item, &arg[0]))
+ all_converted= false;
}
if (all_converted)
m_compare_type= INT_RESULT;
diff --git a/sql/lock.cc b/sql/lock.cc
index 85a32b54081..aba22ebb73d 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -587,22 +587,6 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
}
-/** Abort all other threads waiting to get lock in table. */
-
-void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
-{
- MYSQL_LOCK *locked;
- DBUG_ENTER("mysql_lock_abort");
-
- if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK | GET_LOCK_ON_THD)))
- {
- for (uint i=0; i < locked->lock_count; i++)
- thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
- }
- DBUG_VOID_RETURN;
-}
-
-
/**
Abort one thread / table combination.
diff --git a/sql/lock.h b/sql/lock.h
index 341d7a20f9f..b2de4f60b38 100644
--- a/sql/lock.h
+++ b/sql/lock.h
@@ -33,7 +33,6 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
-void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock);
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
/* Lock based on name */
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 04a616d0006..28374fdd8c9 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -262,6 +262,27 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
}
#endif
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+static void set_thd_db(THD *thd, Rpl_filter *rpl_filter,
+ const char *db, uint32 db_len)
+{
+ char lcase_db_buf[NAME_LEN +1];
+ LEX_STRING new_db;
+ new_db.length= db_len;
+ if (lower_case_table_names == 1)
+ {
+ strmov(lcase_db_buf, db);
+ my_casedn_str(system_charset_info, lcase_db_buf);
+ new_db.str= lcase_db_buf;
+ }
+ else
+ new_db.str= (char*) db;
+ /* TODO WARNING this makes rewrite_db respect lower_case_table_names values
+ * for more info look MDEV-17446 */
+ new_db.str= (char*) rpl_filter->get_rewrite_db(new_db.str, &new_db.length);
+ thd->set_db(new_db.str, new_db.length);
+}
+#endif
/*
Cache that will automatically be written to a dedicated file on
destruction.
@@ -5043,7 +5064,6 @@ bool test_if_equal_repl_errors(int expected_error, int actual_error)
int Query_log_event::do_apply_event(rpl_group_info *rgi,
const char *query_arg, uint32 q_len_arg)
{
- LEX_STRING new_db;
int expected_error,actual_error= 0;
Schema_specification_st db_options;
uint64 sub_id= 0;
@@ -5074,9 +5094,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
goto end;
}
- new_db.length= db_len;
- new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
- thd->set_db(new_db.str, new_db.length); /* allocates a copy of 'db' */
+ set_thd_db(thd, rpl_filter, db, db_len);
/*
Setting the character set and collation of the current database thd->db.
@@ -5230,7 +5248,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
gtid= rgi->current_gtid;
if (rpl_global_gtid_slave_state->record_gtid(thd, &gtid, sub_id,
- true, false))
+ rgi, false))
{
int errcode= thd->get_stmt_da()->sql_errno();
if (!is_parallel_retry_error(rgi, errcode))
@@ -6869,15 +6887,12 @@ void Load_log_event::set_fields(const char* affected_db,
int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
bool use_rli_only_for_errors)
{
- LEX_STRING new_db;
Relay_log_info const *rli= rgi->rli;
Rpl_filter *rpl_filter= rli->mi->rpl_filter;
DBUG_ENTER("Load_log_event::do_apply_event");
- new_db.length= db_len;
- new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
- thd->set_db(new_db.str, new_db.length);
DBUG_ASSERT(thd->query() == 0);
+ set_thd_db(thd, rpl_filter, db, db_len);
thd->clear_error(1);
/* see Query_log_event::do_apply_event() and BUG#13360 */
@@ -6920,6 +6935,8 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
TABLE_LIST tables;
+ if (lower_case_table_names)
+ my_casedn_str(system_charset_info, (char *)table_name);
tables.init_one_table(thd->strmake(thd->db, thd->db_length),
thd->db_length,
table_name, strlen(table_name),
@@ -7947,7 +7964,7 @@ Gtid_list_log_event::do_apply_event(rpl_group_info *rgi)
{
if ((ret= rpl_global_gtid_slave_state->record_gtid(thd, &list[i],
sub_id_list[i],
- false, false)))
+ NULL, false)))
return ret;
rpl_global_gtid_slave_state->update_state_hash(sub_id_list[i], &list[i],
NULL);
@@ -8454,7 +8471,7 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi)
rgi->gtid_pending= false;
gtid= rgi->current_gtid;
- err= rpl_global_gtid_slave_state->record_gtid(thd, &gtid, sub_id, true,
+ err= rpl_global_gtid_slave_state->record_gtid(thd, &gtid, sub_id, rgi,
false);
if (err)
{
@@ -12036,7 +12053,7 @@ check_table_map(rpl_group_info *rgi, RPL_TABLE_LIST *table_list)
int Table_map_log_event::do_apply_event(rpl_group_info *rgi)
{
RPL_TABLE_LIST *table_list;
- char *db_mem, *tname_mem;
+ char *db_mem, *tname_mem, *ptr;
size_t dummy_len;
void *memory;
Rpl_filter *filter;
@@ -12053,10 +12070,20 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi)
NullS)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ strmov(db_mem, m_dbnam);
+ strmov(tname_mem, m_tblnam);
+ if (lower_case_table_names)
+ {
+ my_casedn_str(files_charset_info, (char*)tname_mem);
+ my_casedn_str(files_charset_info, (char*)db_mem);
+ }
+
/* call from mysql_client_binlog_statement() will not set rli->mi */
filter= rgi->thd->slave_thread ? rli->mi->rpl_filter : global_rpl_filter;
- strmov(db_mem, filter->get_rewrite_db(m_dbnam, &dummy_len));
- strmov(tname_mem, m_tblnam);
+
+ /* rewrite rules changed the database */
+ if (((ptr= (char*) filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem))
+ strmov(db_mem, ptr);
table_list->init_one_table(db_mem, strlen(db_mem),
tname_mem, strlen(tname_mem),
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a79cf7eecde..77736607e22 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1785,7 +1785,14 @@ static void close_connections(void)
(ulong) tmp->thread_id,
(tmp->main_security_ctx.user ?
tmp->main_security_ctx.user : ""));
+ /*
+ close_connection() might need a valid current_thd
+ for memory allocation tracking.
+ */
+ THD* save_thd= current_thd;
+ set_current_thd(tmp);
close_connection(tmp,ER_SERVER_SHUTDOWN);
+ set_current_thd(save_thd);
}
#endif
@@ -4402,6 +4409,11 @@ static int init_common_variables()
/* MyISAM requires two file handles per table. */
wanted_files= (extra_files + max_connections + extra_max_connections +
tc_size * 2);
+#if defined(HAVE_POOL_OF_THREADS) && !defined(__WIN__)
+ // add epoll or kevent fd for each threadpool group, in case pool of threads is used
+ wanted_files+= (thread_handling > SCHEDULER_NO_THREADS) ? 0 : threadpool_size;
+#endif
+
min_tc_size= MY_MIN(tc_size, TABLE_OPEN_CACHE_MIN);
org_max_connections= max_connections;
org_tc_size= tc_size;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b67661e1c8a..c5cd615ead2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3128,6 +3128,12 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
}
+ if (quick && (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
+ quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE))
+ {
+ table->cond_selectivity*= (quick->records/table_records);
+ }
+
bitmap_union(used_fields, &handled_columns);
/* Check if we can improve selectivity estimates by using sampling */
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index c933ad4a0ab..f700f7411ca 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -77,7 +77,7 @@ rpl_slave_state::record_and_update_gtid(THD *thd, rpl_group_info *rgi)
rgi->gtid_pending= false;
if (rgi->gtid_ignore_duplicate_state!=rpl_group_info::GTID_DUPLICATE_IGNORE)
{
- if (record_gtid(thd, &rgi->current_gtid, sub_id, false, false))
+ if (record_gtid(thd, &rgi->current_gtid, sub_id, NULL, false))
DBUG_RETURN(1);
update_state_hash(sub_id, &rgi->current_gtid, rgi);
}
@@ -328,6 +328,10 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id,
}
}
rgi->gtid_ignore_duplicate_state= rpl_group_info::GTID_DUPLICATE_NULL;
+
+#ifdef HAVE_REPLICATION
+ rgi->pending_gtid_deletes_clear();
+#endif
}
if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME))))
@@ -377,15 +381,24 @@ int
rpl_slave_state::put_back_list(uint32 domain_id, list_element *list)
{
element *e;
+ int err= 0;
+
+ mysql_mutex_lock(&LOCK_slave_state);
if (!(e= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0)))
- return 1;
+ {
+ err= 1;
+ goto end;
+ }
while (list)
{
list_element *next= list->next;
e->add(list);
list= next;
}
- return 0;
+
+end:
+ mysql_mutex_unlock(&LOCK_slave_state);
+ return err;
}
@@ -470,12 +483,12 @@ gtid_check_rpl_slave_state_table(TABLE *table)
/*
Write a gtid to the replication slave state table.
- Do it as part of the transaction, to get slave crash safety, or as a separate
- transaction if !in_transaction (eg. MyISAM or DDL).
-
gtid The global transaction id for this event group.
sub_id Value allocated within the sub_id when the event group was
read (sub_id must be consistent with commit order in master binlog).
+ rgi rpl_group_info context, if we are recording the gtid transactionally
+ as part of replicating a transactional event. NULL if called from
+ outside of a replicated transaction.
Note that caller must later ensure that the new gtid and sub_id is inserted
into the appropriate HASH element with rpl_slave_state.add(), so that it can
@@ -483,13 +496,13 @@ gtid_check_rpl_slave_state_table(TABLE *table)
*/
int
rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
- bool in_transaction, bool in_statement)
+ rpl_group_info *rgi, bool in_statement)
{
TABLE_LIST tlist;
int err= 0;
bool table_opened= false;
TABLE *table;
- list_element *elist= 0, *next;
+ list_element *elist= 0, *cur, *next;
element *elem;
ulonglong thd_saved_option= thd->variables.option_bits;
Query_tables_list lex_backup;
@@ -560,7 +573,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
thd->wsrep_ignore_table= true;
#endif
- if (!in_transaction)
+ if (!rgi)
{
DBUG_PRINT("info", ("resetting OPTION_BEGIN"));
thd->variables.option_bits&=
@@ -603,9 +616,9 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
if ((elist= elem->grab_list()) != NULL)
{
/* Delete any old stuff, but keep around the most recent one. */
- list_element *cur= elist;
- uint64 best_sub_id= cur->sub_id;
+ uint64 best_sub_id= elist->sub_id;
list_element **best_ptr_ptr= &elist;
+ cur= elist;
while ((next= cur->next))
{
if (next->sub_id > best_sub_id)
@@ -638,7 +651,8 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
table->file->print_error(err, MYF(0));
goto end;
}
- while (elist)
+ cur = elist;
+ while (cur)
{
uchar key_buffer[4+8];
@@ -648,9 +662,9 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
/* `break' does not work inside DBUG_EXECUTE_IF */
goto dbug_break; });
- next= elist->next;
+ next= cur->next;
- table->field[1]->store(elist->sub_id, true);
+ table->field[1]->store(cur->sub_id, true);
/* domain_id is already set in table->record[0] from write_row() above. */
key_copy(key_buffer, table->record[0], &table->key_info[0], 0, false);
if (table->file->ha_index_read_map(table->record[1], key_buffer,
@@ -664,8 +678,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
not want to endlessly error on the same element in case of table
corruption or such.
*/
- my_free(elist);
- elist= next;
+ cur= next;
if (err)
break;
}
@@ -688,18 +701,35 @@ end:
*/
if (elist)
{
- mysql_mutex_lock(&LOCK_slave_state);
put_back_list(gtid->domain_id, elist);
- mysql_mutex_unlock(&LOCK_slave_state);
+ elist = 0;
}
ha_rollback_trans(thd, FALSE);
}
close_thread_tables(thd);
- if (in_transaction)
+ if (rgi)
+ {
thd->mdl_context.release_statement_locks();
+ /*
+ Save the list of old gtid entries we deleted. If this transaction
+ fails later for some reason and is rolled back, the deletion of those
+ entries will be rolled back as well, and we will need to put them back
+ on the to-be-deleted list so we can re-do the deletion. Otherwise
+ redundant rows in mysql.gtid_slave_pos may accumulate if transactions
+ are rolled back and retried after record_gtid().
+ */
+#ifdef HAVE_REPLICATION
+ rgi->pending_gtid_deletes_save(gtid->domain_id, elist);
+#endif
+ }
else
+ {
thd->mdl_context.release_transactional_locks();
+#ifdef HAVE_REPLICATION
+ rpl_group_info::pending_gtid_deletes_free(elist);
+#endif
+ }
}
thd->lex->restore_backup_query_tables_list(&lex_backup);
thd->variables.option_bits= thd_saved_option;
@@ -1082,7 +1112,7 @@ rpl_slave_state::load(THD *thd, char *state_from_master, size_t len,
if (gtid_parser_helper(&state_from_master, end, &gtid) ||
!(sub_id= next_sub_id(gtid.domain_id)) ||
- record_gtid(thd, &gtid, sub_id, false, in_statement) ||
+ record_gtid(thd, &gtid, sub_id, NULL, in_statement) ||
update(gtid.domain_id, gtid.server_id, sub_id, gtid.seq_no, NULL))
return 1;
if (state_from_master == end)
@@ -1817,10 +1847,10 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
for (ulong i= 0; i < ids->elements; i++)
{
rpl_binlog_state::element *elem= NULL;
- ulong *ptr_domain_id;
+ uint32 *ptr_domain_id;
bool not_match;
- ptr_domain_id= (ulong*) dynamic_array_ptr(ids, i);
+ ptr_domain_id= (uint32*) dynamic_array_ptr(ids, i);
elem= (rpl_binlog_state::element *)
my_hash_search(&hash, (const uchar *) ptr_domain_id, 0);
if (!elem)
@@ -1841,7 +1871,7 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
if (not_match)
{
- sprintf(errbuf, "binlog files may contain gtids from the domain ('%lu') "
+ sprintf(errbuf, "binlog files may contain gtids from the domain ('%u') "
"being deleted. Make sure to first purge those files",
*ptr_domain_id);
errmsg= errbuf;
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index 1230b6fd3bc..35744bc35b1 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -182,7 +182,7 @@ struct rpl_slave_state
uint64 seq_no, rpl_group_info *rgi);
int truncate_state_table(THD *thd);
int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
- bool in_transaction, bool in_statement);
+ rpl_group_info *rgi, bool in_statement);
uint64 next_sub_id(uint32 domain_id);
int iterate(int (*cb)(rpl_gtid *, void *), void *data,
rpl_gtid *extra_gtids, uint32 num_extra,
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index ed9f0369f5d..26b93da3917 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1702,6 +1702,7 @@ rpl_group_info::reinit(Relay_log_info *rli)
long_find_row_note_printed= false;
did_mark_start_commit= false;
gtid_ev_flags2= 0;
+ pending_gtid_delete_list= NULL;
last_master_timestamp = 0;
gtid_ignore_duplicate_state= GTID_DUPLICATE_NULL;
speculation= SPECULATE_NO;
@@ -1832,6 +1833,12 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
erroneously update the GTID position.
*/
gtid_pending= false;
+
+ /*
+ Rollback will have undone any deletions of old rows we might have made
+ in mysql.gtid_slave_pos. Put those rows back on the list to be deleted.
+ */
+ pending_gtid_deletes_put_back();
}
m_table_map.clear_tables();
slave_close_thread_tables(thd);
@@ -2057,6 +2064,78 @@ rpl_group_info::unmark_start_commit()
}
+/*
+ When record_gtid() has deleted any old rows from the table
+ mysql.gtid_slave_pos as part of a replicated transaction, save the list of
+ rows deleted here.
+
+ If later the transaction fails (eg. optimistic parallel replication), the
+ deletes will be undone when the transaction is rolled back. Then we can
+ put back the list of rows into the rpl_global_gtid_slave_state, so that
+ we can re-do the deletes and avoid accumulating old rows in the table.
+*/
+void
+rpl_group_info::pending_gtid_deletes_save(uint32 domain_id,
+ rpl_slave_state::list_element *list)
+{
+ /*
+ We should never get to a state where we try to save a new pending list of
+ gtid deletes while we still have an old one. But make sure we handle it
+ anyway just in case, so we avoid leaving stray entries in the
+ mysql.gtid_slave_pos table.
+ */
+ DBUG_ASSERT(!pending_gtid_delete_list);
+ if (unlikely(pending_gtid_delete_list))
+ pending_gtid_deletes_put_back();
+
+ pending_gtid_delete_list= list;
+ pending_gtid_delete_list_domain= domain_id;
+}
+
+
+/*
+ Take the list recorded by pending_gtid_deletes_save() and put it back into
+ rpl_global_gtid_slave_state. This is needed if deletion of the rows was
+ rolled back due to transaction failure.
+*/
+void
+rpl_group_info::pending_gtid_deletes_put_back()
+{
+ if (pending_gtid_delete_list)
+ {
+ rpl_global_gtid_slave_state->put_back_list(pending_gtid_delete_list_domain,
+ pending_gtid_delete_list);
+ pending_gtid_delete_list= NULL;
+ }
+}
+
+
+/*
+ Free the list recorded by pending_gtid_deletes_save(). Done when the deletes
+ in the list have been permanently committed.
+*/
+void
+rpl_group_info::pending_gtid_deletes_clear()
+{
+ pending_gtid_deletes_free(pending_gtid_delete_list);
+ pending_gtid_delete_list= NULL;
+}
+
+
+void
+rpl_group_info::pending_gtid_deletes_free(rpl_slave_state::list_element *list)
+{
+ rpl_slave_state::list_element *next;
+
+ while (list)
+ {
+ next= list->next;
+ my_free(list);
+ list= next;
+ }
+}
+
+
rpl_sql_thread_info::rpl_sql_thread_info(Rpl_filter *filter)
: rpl_filter(filter)
{
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index d88bc9f6ecd..564582a47be 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -757,6 +757,11 @@ struct rpl_group_info
/* Needs room for "Gtid D-S-N\x00". */
char gtid_info_buf[5+10+1+10+1+20+1];
+ /* List of not yet committed deletions in mysql.gtid_slave_pos. */
+ rpl_slave_state::list_element *pending_gtid_delete_list;
+ /* Domain associated with pending_gtid_delete_list. */
+ uint32 pending_gtid_delete_list_domain;
+
/*
The timestamp, from the master, of the commit event.
Used to do delayed update of rli->last_master_timestamp, for getting
@@ -898,6 +903,12 @@ struct rpl_group_info
char *gtid_info();
void unmark_start_commit();
+ static void pending_gtid_deletes_free(rpl_slave_state::list_element *list);
+ void pending_gtid_deletes_save(uint32 domain_id,
+ rpl_slave_state::list_element *list);
+ void pending_gtid_deletes_put_back();
+ void pending_gtid_deletes_clear();
+
time_t get_row_stmt_start_timestamp()
{
return row_stmt_start_timestamp;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index fd213c528e1..4c2649cea56 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3433,7 +3433,7 @@ end:
close_mysql_tables(thd);
#ifdef WITH_WSREP
-error: // this label is used in WSREP_TO_ISOLATION_BEGIN
+WSREP_ERROR_LABEL:
if (WSREP(thd) && !thd->wsrep_applier)
{
WSREP_TO_ISOLATION_END;
@@ -3595,7 +3595,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
}
#ifdef WITH_WSREP
-error: // this label is used in WSREP_TO_ISOLATION_END
+WSREP_ERROR_LABEL:
if (WSREP(thd) && !thd->wsrep_applier)
{
WSREP_TO_ISOLATION_END;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index a14a8cd0945..edb94019cc6 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1321,6 +1321,7 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
+WSREP_ERROR_LABEL:
DBUG_RETURN(res);
}
@@ -1379,6 +1380,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
+WSREP_ERROR_LABEL:
DBUG_RETURN(res);
}
@@ -1413,5 +1415,6 @@ bool Sql_cmd_repair_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
+WSREP_ERROR_LABEL:
DBUG_RETURN(res);
}
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index c8bc3952b61..f76c4046ee0 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -329,13 +329,10 @@ bool Sql_cmd_alter_table::execute(THD *thd)
lex->ignore);
DBUG_RETURN(result);
-#ifdef WITH_WSREP
-error:
- {
- WSREP_WARN("ALTER TABLE isolation failure");
- DBUG_RETURN(TRUE);
- }
-#endif /* WITH_WSREP */
+
+WSREP_ERROR_LABEL:
+ WSREP_WARN("ALTER TABLE isolation failure");
+ DBUG_RETURN(TRUE);
}
bool Sql_cmd_discard_import_tablespace::execute(THD *thd)
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 4c75bd4a509..e33efc9476f 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -166,7 +166,7 @@ public:
// Columns and keys to be dropped.
List<Alter_drop> drop_list;
- // Columns for ALTER_COLUMN_CHANGE_DEFAULT.
+ // Columns for ALTER_CHANGE_COLUMN_DEFAULT.
List<Alter_column> alter_list;
// List of keys, used by both CREATE and ALTER TABLE.
List<Key> key_list;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e1db8bc48be..c282db42fdd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4185,6 +4185,7 @@ restart:
}
error:
+WSREP_ERROR_LABEL:
THD_STAGE_INFO(thd, stage_after_opening_tables);
thd_proc_info(thd, 0);
@@ -8409,84 +8410,6 @@ my_bool mysql_rm_tmp_tables(void)
unireg support functions
*****************************************************************************/
-/**
- A callback to the server internals that is used to address
- special cases of the locking protocol.
- Invoked when acquiring an exclusive lock, for each thread that
- has a conflicting shared metadata lock.
-
- This function:
- - aborts waiting of the thread on a data lock, to make it notice
- the pending exclusive lock and back off.
- - if the thread is an INSERT DELAYED thread, sends it a KILL
- signal to terminate it.
-
- @note This function does not wait for the thread to give away its
- locks. Waiting is done outside for all threads at once.
-
- @param thd Current thread context
- @param in_use The thread to wake up
- @param needs_thr_lock_abort Indicates that to wake up thread
- this call needs to abort its waiting
- on table-level lock.
-
- @retval TRUE if the thread was woken up
- @retval FALSE otherwise.
-
- @note It is one of two places where border between MDL and the
- rest of the server is broken.
-*/
-
-bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use,
- bool needs_thr_lock_abort)
-{
- bool signalled= FALSE;
- if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
- !in_use->killed)
- {
- in_use->set_killed(KILL_SYSTEM_THREAD);
- mysql_mutex_lock(&in_use->mysys_var->mutex);
- if (in_use->mysys_var->current_cond)
- {
- mysql_mutex_lock(in_use->mysys_var->current_mutex);
- mysql_cond_broadcast(in_use->mysys_var->current_cond);
- mysql_mutex_unlock(in_use->mysys_var->current_mutex);
- }
- mysql_mutex_unlock(&in_use->mysys_var->mutex);
- signalled= TRUE;
- }
-
- if (needs_thr_lock_abort)
- {
- mysql_mutex_lock(&in_use->LOCK_thd_data);
- for (TABLE *thd_table= in_use->open_tables;
- thd_table ;
- thd_table= thd_table->next)
- {
- /*
- Check for TABLE::needs_reopen() is needed since in some places we call
- handler::close() for table instance (and set TABLE::db_stat to 0)
- and do not remove such instances from the THD::open_tables
- for some time, during which other thread can see those instances
- (e.g. see partitioning code).
- */
- if (!thd_table->needs_reopen())
- {
- signalled|= mysql_lock_abort_for_thread(thd, thd_table);
- if (thd && WSREP(thd) && wsrep_thd_is_BF(thd, true))
- {
- WSREP_DEBUG("remove_table_from_cache: %llu",
- (unsigned long long) thd->real_id);
- wsrep_abort_thd((void *)thd, (void *)in_use, FALSE);
- }
- }
- }
- mysql_mutex_unlock(&in_use->LOCK_thd_data);
- }
- return signalled;
-}
-
-
int setup_ftfuncs(SELECT_LEX *select_lex)
{
List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)),
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index bdb2d6caf25..9821848bb2f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2422,7 +2422,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
The thread could be killed with an error message if
di->handle_inserts() or di->open_and_lock_table() fails.
The thread could be killed without an error message if
- killed using mysql_notify_thread_having_shared_lock() or
+ killed using THD::notify_shared_lock() or
kill_delayed_threads_for_table().
*/
if (!thd.is_error())
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3624b238fbc..7b7693036b2 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2944,7 +2944,7 @@ LEX::LEX()
INITIAL_LEX_PLUGIN_LIST_SIZE, 0);
reset_query_tables_list(TRUE);
mi.init();
- init_dynamic_array2(&delete_gtid_domain, sizeof(ulong*),
+ init_dynamic_array2(&delete_gtid_domain, sizeof(uint32),
gtid_domain_static_buffer,
initial_gtid_domain_buffer_size,
initial_gtid_domain_buffer_size, 0);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 939b48ba825..76e280175a1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -2876,7 +2876,7 @@ public:
*/
DYNAMIC_ARRAY delete_gtid_domain;
static const ulong initial_gtid_domain_buffer_size= 16;
- ulong gtid_domain_static_buffer[initial_gtid_domain_buffer_size];
+ uint32 gtid_domain_static_buffer[initial_gtid_domain_buffer_size];
inline void set_limit_rows_examined()
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3231c4b730f..3bacf1494b7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6238,6 +6238,7 @@ end_with_restore_list:
goto finish;
error:
+WSREP_ERROR_LABEL:
res= TRUE;
finish:
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index cb5b3c8a044..c13a4296996 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -1,6 +1,6 @@
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, SkySQL Ab.
- Copyright (c) 2016, MariaDB Corporation
+ Copyright (c) 2016, 2018, MariaDB Corporation.
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
@@ -94,7 +94,7 @@ bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd)
thd->enable_slow_log= opt_log_slow_admin_statements;
DBUG_RETURN(exchange_partition(thd, first_table, &alter_info));
#ifdef WITH_WSREP
- error:
+ wsrep_error_label:
/* handle errors in TO_ISOLATION here */
DBUG_RETURN(true);
#endif /* WITH_WSREP */
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 58dd9c95f10..da83eae8f0a 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2197,10 +2197,9 @@ err:
if (argv)
free_defaults(argv);
DBUG_RETURN(error);
-#ifdef WITH_WSREP
-error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
}
@@ -2343,10 +2342,9 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
mysql_mutex_unlock(&LOCK_plugin);
DBUG_RETURN(error);
-#ifdef WITH_WSREP
-error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(TRUE);
-#endif /* WITH_WSREP */
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index ba4a2725ced..4f1ee2b4c1a 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -621,10 +621,9 @@ end:
my_ok(thd);
DBUG_RETURN(result);
-#ifdef WITH_WSREP
- error:
+
+WSREP_ERROR_LABEL:
DBUG_RETURN(true);
-#endif /* WITH_WSREP */
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index d9cc470961e..91b811fbb93 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -700,10 +700,10 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
DBUG_RETURN(0);
-#ifdef WITH_WSREP
- error:
+
+WSREP_ERROR_LABEL:
res= TRUE;
-#endif /* WITH_WSREP */
+
err:
THD_STAGE_INFO(thd, stage_end);
lex->link_first_table_back(view, link_to_local);
@@ -1546,8 +1546,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
{
tbl->lock_type= table->lock_type;
- tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ?
- MDL_SHARED_WRITE : MDL_SHARED_READ);
+ tbl->mdl_request.set_type(table->mdl_request.type);
}
/*
If the view is mergeable, we might want to
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 67c757893d1..6720f620b61 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13403,9 +13403,18 @@ delete_domain_id_list:
;
delete_domain_id:
- ulong_num
+ ulonglong_num
{
- insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &($1));
+ uint32 value= (uint32) $1;
+ if ($1 > UINT_MAX32)
+ {
+ my_printf_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
+ "The value of gtid domain being deleted ('%llu') "
+ "exceeds its maximum size "
+ "of 32 bit unsigned integer", MYF(0), $1);
+ MYSQL_YYABORT;
+ }
+ insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &value);
}
;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0ddc4520cee..da5042ee16d 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -2743,7 +2743,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
return(false);
-error:
+WSREP_ERROR_LABEL:
thd->wsrep_TOI_pre_query= NULL;
return (true);
}