MDEV-25642 InnoDB rename table copy DDL fails while dropping the table

When doing a ALTER TABLE ... RENAME, MariaDB doesn't rename
original table to #sql-backup, which it does in other cases,
but insteads drops the original table directly. However
this optimization doesn't work in case of InnoDB table
with a foreign key constraint.

During copy algorithm, InnoDB fails to rename the foreign key
constraint(MDEV-25855). With this optimisation, InnoDB also
fails to drop the original table because the table has
FOREIGN Key constraint exist in INNODB_SYS_FOREIGN table.
This leads to orphan .ibd file in InnoDB dictionary.
so disabling this optimization when FK is involved.

Reviewer: monty@mariadb.org
parent b25d2a45
...@@ -206,3 +206,18 @@ c0123456789012345678 int, ...@@ -206,3 +206,18 @@ c0123456789012345678 int,
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3) FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
#
# MDEV-25642 InnoDB rename table copy DDL fails
# while dropping the table
#
call mtr.add_suppression("InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1_fk (a VARCHAR(40), KEY a (a), FULLTEXT KEY(a), CONSTRAINT fk FOREIGN KEY(a) REFERENCES t1 (a) ON UPDATE CASCADE) ENGINE=InnoDB;
ALTER TABLE t1 RENAME TO tm1, ALGORITHM=COPY;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
ID FOR_NAME REF_NAME N_COLS TYPE
test/fk test/t1_fk test/t1 1 4
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE t1 (c1 BIGINT NOT NULL, c2 BIGINT NOT NULL, PRIMARY KEY(c1), UNIQUE KEY(c2)) ENGINE=MEMORY;
ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=COPY;
DROP TABLE t1, tm1, t1_fk;
...@@ -244,3 +244,19 @@ CREATE TABLE t1 ( ...@@ -244,3 +244,19 @@ CREATE TABLE t1 (
c0123456789012345678 int, c0123456789012345678 int,
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3) FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
--echo #
--echo # MDEV-25642 InnoDB rename table copy DDL fails
--echo # while dropping the table
--echo #
call mtr.add_suppression("InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1_fk (a VARCHAR(40), KEY a (a), FULLTEXT KEY(a), CONSTRAINT fk FOREIGN KEY(a) REFERENCES t1 (a) ON UPDATE CASCADE) ENGINE=InnoDB;
ALTER TABLE t1 RENAME TO tm1, ALGORITHM=COPY;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
# Enable SET FOREIGN_KEY_CHECKS after fixing MDEV-25885
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE t1 (c1 BIGINT NOT NULL, c2 BIGINT NOT NULL, PRIMARY KEY(c1), UNIQUE KEY(c2)) ENGINE=MEMORY;
ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=COPY;
DROP TABLE t1, tm1, t1_fk;
...@@ -11009,7 +11009,12 @@ do_continue:; ...@@ -11009,7 +11009,12 @@ do_continue:;
DBUG_PRINT("info", ("is_table_renamed: %d engine_changed: %d", DBUG_PRINT("info", ("is_table_renamed: %d engine_changed: %d",
alter_ctx.is_table_renamed(), engine_changed)); alter_ctx.is_table_renamed(), engine_changed));
if (!alter_ctx.is_table_renamed()) /*
InnoDB cannot use the rename optimization when foreign key
constraint is involved because InnoDB fails to drop the
parent table due to foreign key constraint
*/
if (!alter_ctx.is_table_renamed() || alter_ctx.fk_error_if_delete_row)
{ {
backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff), backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff),
"%s-backup-%lx-%llx", tmp_file_prefix, "%s-backup-%lx-%llx", tmp_file_prefix,
...@@ -11044,7 +11049,7 @@ do_continue:; ...@@ -11044,7 +11049,7 @@ do_continue:;
(void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db, (void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
&alter_ctx.tmp_name, FN_IS_TMP); &alter_ctx.tmp_name, FN_IS_TMP);
if (!alter_ctx.is_table_renamed()) if (!alter_ctx.is_table_renamed() || alter_ctx.fk_error_if_delete_row)
{ {
// Restore the backup of the original table to the old name. // Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name, (void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment