diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-06 08:41:48 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-06 08:41:48 +0200 |
commit | 32062cc61cd00e4cd3b7939c8a09f9c3ac34ec76 (patch) | |
tree | 098d64b7c988bab8cca25b0f716d92f6f7e72ed9 /sql | |
parent | af9649c722810eb1754953eb406a84ec876ce693 (diff) | |
parent | bae21bfb5de17328c33c3da8d191c6d3af14ae02 (diff) | |
download | mariadb-git-32062cc61cd00e4cd3b7939c8a09f9c3ac34ec76.tar.gz |
Merge 10.1 into 10.2
Diffstat (limited to 'sql')
-rw-r--r-- | sql/CMakeLists.txt | 2 | ||||
-rw-r--r-- | sql/compat56.cc | 3 | ||||
-rw-r--r-- | sql/events.cc | 16 | ||||
-rw-r--r-- | sql/field_conv.cc | 2 | ||||
-rw-r--r-- | sql/ha_partition.cc | 9 | ||||
-rw-r--r-- | sql/ha_partition.h | 1 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 15 | ||||
-rw-r--r-- | sql/lock.cc | 16 | ||||
-rw-r--r-- | sql/lock.h | 1 | ||||
-rw-r--r-- | sql/log_event.cc | 55 | ||||
-rw-r--r-- | sql/mysqld.cc | 12 | ||||
-rw-r--r-- | sql/opt_range.cc | 6 | ||||
-rw-r--r-- | sql/rpl_gtid.cc | 76 | ||||
-rw-r--r-- | sql/rpl_gtid.h | 2 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 79 | ||||
-rw-r--r-- | sql/rpl_rli.h | 11 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | sql/sql_admin.cc | 3 | ||||
-rw-r--r-- | sql/sql_alter.cc | 11 | ||||
-rw-r--r-- | sql/sql_alter.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 79 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_partition_admin.cc | 4 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 10 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 5 | ||||
-rw-r--r-- | sql/sql_view.cc | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 13 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 2 |
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, >id, 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, >id, sub_id, true, + err= rpl_global_gtid_slave_state->record_gtid(thd, >id, 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, >id) || !(sub_id= next_sub_id(gtid.domain_id)) || - record_gtid(thd, >id, sub_id, false, in_statement) || + record_gtid(thd, >id, 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); } |