From d0b73fb8d3ae4ef9ec2cde945fa6ada512f762fe Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 29 Mar 2019 19:08:22 +0400 Subject: MDEV-16060 - InnoDB: Failing assertion: ut_strcmp(index->name, key->name) A sequel to 9180e86 and 149b754. ALTER TABLE ... ADD FOREIGN KEY may crash if parent table is updated concurrently. Block FK parent table updates even earlier, before intermediate child table is created. Use proper charset info for my_casedn_str() and don't update original identifiers so that lower_cast_table_names == 2 is honoured. --- sql/sql_table.cc | 91 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 46 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 57333e7dc30..463aab9f589 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8242,6 +8242,50 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table, } } + /* + Normally, an attempt to modify an FK parent table will cause + FK children to be prelocked, so the table-being-altered cannot + be modified by a cascade FK action, because ALTER holds a lock + and prelocking will wait. + + But if a new FK is being added by this very ALTER, then the target + table is not locked yet (it's a temporary table). So, we have to + lock FK parents explicitly. + */ + if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY) + { + List_iterator fk_list_it(alter_info->key_list); + + while (Key *key= fk_list_it++) + { + if (key->type != Key::FOREIGN_KEY) + continue; + + Foreign_key *fk= static_cast(key); + char dbuf[NAME_LEN]; + char tbuf[NAME_LEN]; + const char *ref_db= fk->ref_db.str ? fk->ref_db.str : alter_ctx->new_db; + const char *ref_table= fk->ref_table.str; + MDL_request mdl_request; + + if (lower_case_table_names) + { + strmake_buf(dbuf, ref_db); + my_casedn_str(system_charset_info, dbuf); + strmake_buf(tbuf, ref_table); + my_casedn_str(system_charset_info, tbuf); + ref_db= dbuf; + ref_table= tbuf; + } + + mdl_request.init(MDL_key::TABLE, ref_db, ref_table, MDL_SHARED_NO_WRITE, + MDL_TRANSACTION); + if (thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(true); + } + } + DBUG_RETURN(false); } @@ -9093,6 +9137,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* Mark that we have created table in storage engine. */ no_ha_table= false; + DEBUG_SYNC(thd, "alter_table_intermediate_table_created"); if (create_info->tmp_table()) { @@ -9126,52 +9171,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, true, true); if (!new_table) goto err_new_table_cleanup; - - /* - Normally, an attempt to modify an FK parent table will cause - FK children to be prelocked, so the table-being-altered cannot - be modified by a cascade FK action, because ALTER holds a lock - and prelocking will wait. - - But if a new FK is being added by this very ALTER, then the target - table is not locked yet (it's a temporary table). So, we have to - lock FK parents explicitly. - */ - if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY) - { - List fk_list; - List_iterator fk_list_it(fk_list); - FOREIGN_KEY_INFO *fk; - - /* tables_opened can be > 1 only for MERGE tables */ - DBUG_ASSERT(tables_opened == 1); - DBUG_ASSERT(&table_list->next_global == thd->lex->query_tables_last); - - new_table->file->get_foreign_key_list(thd, &fk_list); - while ((fk= fk_list_it++)) - { - MDL_request mdl_request; - - if (lower_case_table_names) - { - char buf[NAME_LEN]; - uint len; - strmake_buf(buf, fk->referenced_db->str); - len = my_casedn_str(files_charset_info, buf); - thd->make_lex_string(fk->referenced_db, buf, len); - strmake_buf(buf, fk->referenced_table->str); - len = my_casedn_str(files_charset_info, buf); - thd->make_lex_string(fk->referenced_table, buf, len); - } - - mdl_request.init(MDL_key::TABLE, - fk->referenced_db->str, fk->referenced_table->str, - MDL_SHARED_NO_WRITE, MDL_TRANSACTION); - if (thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) - goto err_new_table_cleanup; - } - } } /* Note: In case of MERGE table, we do not attach children. We do not -- cgit v1.2.1 From d0ee3b5500cdaf3382fc8f26c883f45d8f4bdf5b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 9 May 2019 16:55:08 +0200 Subject: MDEV-19427 mysql_upgrade_service throws exception upgrading from 10.0 to 10.3 The crash happens when writing into log file. The reason is likely that the call to WriteFile() was missing a valid parameter for lpNumberOfBytesWritten. This seems only to happen on ancient version of Windows. Since the fix to MDEV-16430 in 141bc58ac992, null pointer was passed instead of valid pointer. The fix is to provide a valid lpNumberOfBytesWritten parameter. --- sql/mysql_upgrade_service.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc index 9bb60809205..ef01afe899d 100644 --- a/sql/mysql_upgrade_service.cc +++ b/sql/mysql_upgrade_service.cc @@ -148,8 +148,9 @@ static void die(const char *fmt, ...) #define WRITE_LOG(fmt,...) {\ char log_buf[1024]; \ + DWORD nbytes; \ snprintf(log_buf,sizeof(log_buf), fmt, __VA_ARGS__);\ - WriteFile(logfile_handle,log_buf, strlen(log_buf), 0 , 0);\ + WriteFile(logfile_handle,log_buf, strlen(log_buf), &nbytes , 0);\ } /* -- cgit v1.2.1 From 06442e3e9f7819a982eb7a4dc865be02c556ab06 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 6 May 2019 22:30:35 +0300 Subject: MDEV-19399 do not call slow my_timer_init() several times No functional change. Call my_timer_init() only once and then reuse it from InnoDB and perfschema storage engines. This patch speeds up empty test for me like this: ./mtr -mem innodb.kevg,xtradb 1.21s user 0.84s system 34% cpu 5.999 total ./mtr -mem innodb.kevg,xtradb 1.12s user 0.60s system 31% cpu 5.385 total --- sql/mysqld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysqld.h b/sql/mysqld.h index af519622d97..92e048d3f6e 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -64,7 +64,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ #define OPT_SESSION SHOW_OPT_SESSION #define OPT_GLOBAL SHOW_OPT_GLOBAL -extern MY_TIMER_INFO sys_timer_info; +extern MYSQL_PLUGIN_IMPORT MY_TIMER_INFO sys_timer_info; /* Values for --slave-parallel-mode -- cgit v1.2.1