summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/create-big.result4
-rw-r--r--mysql-test/t/create-big.test27
-rw-r--r--sql/sql_table.cc28
-rw-r--r--storage/innobase/handler/ha_innodb.cc3
4 files changed, 49 insertions, 13 deletions
diff --git a/mysql-test/r/create-big.result b/mysql-test/r/create-big.result
index 34293d7e5cd..4cce5d8618c 100644
--- a/mysql-test/r/create-big.result
+++ b/mysql-test/r/create-big.result
@@ -53,8 +53,8 @@ set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
create table t1 select 1 as i;;
set debug_sync='now WAIT_FOR parked';
alter table t3 rename to t1;
-ERROR 42S01: Table 't1' already exists
set debug_sync='now SIGNAL go';
+ERROR 42S01: Table 't1' already exists
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -65,8 +65,8 @@ set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
create table t1 select 1 as i;;
set debug_sync='now WAIT_FOR parked';
alter table t3 rename to t1, add k int;
-ERROR 42S01: Table 't1' already exists
set debug_sync='now SIGNAL go';
+ERROR 42S01: Table 't1' already exists
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
diff --git a/mysql-test/t/create-big.test b/mysql-test/t/create-big.test
index d487608f7e1..8d916f8da82 100644
--- a/mysql-test/t/create-big.test
+++ b/mysql-test/t/create-big.test
@@ -132,11 +132,20 @@ set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
--send create table t1 select 1 as i;
connection addconroot1;
set debug_sync='now WAIT_FOR parked';
---error ER_TABLE_EXISTS_ERROR
-alter table t3 rename to t1;
+--send alter table t3 rename to t1
+connection addconroot2;
+# Wait until the above ALTER TABLE RENAME is blocked due to CREATE
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "alter table t3 rename to t1";
+--source include/wait_condition.inc
set debug_sync='now SIGNAL go';
connection default;
--reap
+connection addconroot1;
+--error ER_TABLE_EXISTS_ERROR
+--reap
connection default;
show create table t1;
drop table t1;
@@ -146,11 +155,21 @@ set debug_sync='create_table_select_before_create SIGNAL parked WAIT_FOR go';
--send create table t1 select 1 as i;
connection addconroot1;
set debug_sync='now WAIT_FOR parked';
---error ER_TABLE_EXISTS_ERROR
-alter table t3 rename to t1, add k int;
+--send alter table t3 rename to t1, add k int
+connection addconroot2;
+# Wait until the above ALTER TABLE RENAME is blocked due to CREATE
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "alter table t3 rename to t1, add k int";
+--source include/wait_condition.inc
set debug_sync='now SIGNAL go';
connection default;
--reap
+connection addconroot1;
+--error ER_TABLE_EXISTS_ERROR
+--reap
+connection default;
show create table t1;
drop table t1,t3;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c146079fdb3..60ae2ed800b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5872,8 +5872,26 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
else
{
+ MDL_request_list mdl_requests;
+ MDL_request target_db_mdl_request;
+
target_mdl_request.init(MDL_key::TABLE, new_db, new_name,
MDL_EXCLUSIVE, MDL_TRANSACTION);
+ mdl_requests.push_front(&target_mdl_request);
+
+ /*
+ If we are moving the table to a different database, we also
+ need IX lock on the database name so that the target database
+ is protected by MDL while the table is moved.
+ */
+ if (new_db != db)
+ {
+ target_db_mdl_request.init(MDL_key::SCHEMA, new_db, "",
+ MDL_INTENTION_EXCLUSIVE,
+ MDL_TRANSACTION);
+ mdl_requests.push_front(&target_db_mdl_request);
+ }
+
/*
Global intention exclusive lock must have been already acquired when
table to be altered was open, so there is no need to do it here.
@@ -5882,14 +5900,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
"", "",
MDL_INTENTION_EXCLUSIVE));
- if (thd->mdl_context.try_acquire_lock(&target_mdl_request))
+ if (thd->mdl_context.acquire_locks(&mdl_requests,
+ thd->variables.lock_wait_timeout))
DBUG_RETURN(TRUE);
- if (target_mdl_request.ticket == NULL)
- {
- /* Table exists and is locked by some thread. */
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
- DBUG_RETURN(TRUE);
- }
+
DEBUG_SYNC(thd, "locked_table_name");
/*
Table maybe does not exist, but we got an exclusive lock
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 19644ddc966..9f7290f5b2d 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -47,6 +47,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <sql_acl.h> // PROCESS_ACL
#include <m_ctype.h>
+#include <debug_sync.h> // DEBUG_SYNC
#include <mysys_err.h>
#include <mysql/plugin.h>
#include <mysql/innodb_priv.h>
@@ -7691,6 +7692,8 @@ ha_innobase::rename_table(
error = innobase_rename_table(trx, from, to, TRUE);
+ DEBUG_SYNC(thd, "after_innobase_rename_table");
+
/* Tell the InnoDB server that there might be work for
utility threads: */