Skip to content

Commit 2c6d5c9

Browse files
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
1 parent b25d2a4 commit 2c6d5c9

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

mysql-test/suite/innodb/r/innodb-fk.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,18 @@ c0123456789012345678 int,
206206
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
207207
) ENGINE=InnoDB;
208208
ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
209+
#
210+
# MDEV-25642 InnoDB rename table copy DDL fails
211+
# while dropping the table
212+
#
213+
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.");
214+
CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY) ENGINE=InnoDB;
215+
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;
216+
ALTER TABLE t1 RENAME TO tm1, ALGORITHM=COPY;
217+
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
218+
ID FOR_NAME REF_NAME N_COLS TYPE
219+
test/fk test/t1_fk test/t1 1 4
220+
SET FOREIGN_KEY_CHECKS=0;
221+
CREATE TABLE t1 (c1 BIGINT NOT NULL, c2 BIGINT NOT NULL, PRIMARY KEY(c1), UNIQUE KEY(c2)) ENGINE=MEMORY;
222+
ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=COPY;
223+
DROP TABLE t1, tm1, t1_fk;

mysql-test/suite/innodb/t/innodb-fk.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,19 @@ CREATE TABLE t1 (
244244
c0123456789012345678 int,
245245
FOREIGN KEY (a012345678901234567,c0123456789012345678,b) REFERENCES tx (x1,x2,x3)
246246
) ENGINE=InnoDB;
247+
248+
--echo #
249+
--echo # MDEV-25642 InnoDB rename table copy DDL fails
250+
--echo # while dropping the table
251+
--echo #
252+
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.");
253+
254+
CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY) ENGINE=InnoDB;
255+
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;
256+
ALTER TABLE t1 RENAME TO tm1, ALGORITHM=COPY;
257+
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
258+
# Enable SET FOREIGN_KEY_CHECKS after fixing MDEV-25885
259+
SET FOREIGN_KEY_CHECKS=0;
260+
CREATE TABLE t1 (c1 BIGINT NOT NULL, c2 BIGINT NOT NULL, PRIMARY KEY(c1), UNIQUE KEY(c2)) ENGINE=MEMORY;
261+
ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=COPY;
262+
DROP TABLE t1, tm1, t1_fk;

sql/sql_table.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11009,7 +11009,12 @@ do_continue:;
1100911009
DBUG_PRINT("info", ("is_table_renamed: %d engine_changed: %d",
1101011010
alter_ctx.is_table_renamed(), engine_changed));
1101111011

11012-
if (!alter_ctx.is_table_renamed())
11012+
/*
11013+
InnoDB cannot use the rename optimization when foreign key
11014+
constraint is involved because InnoDB fails to drop the
11015+
parent table due to foreign key constraint
11016+
*/
11017+
if (!alter_ctx.is_table_renamed() || alter_ctx.fk_error_if_delete_row)
1101311018
{
1101411019
backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff),
1101511020
"%s-backup-%lx-%llx", tmp_file_prefix,
@@ -11044,7 +11049,7 @@ do_continue:;
1104411049
(void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
1104511050
&alter_ctx.tmp_name, FN_IS_TMP);
1104611051

11047-
if (!alter_ctx.is_table_renamed())
11052+
if (!alter_ctx.is_table_renamed() || alter_ctx.fk_error_if_delete_row)
1104811053
{
1104911054
// Restore the backup of the original table to the old name.
1105011055
(void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,

0 commit comments

Comments
 (0)