Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MDEV-31086 MODIFY COLUMN can break FK constraints, and lead to unrest…
…orable dumps - When foreign_key_check is disabled, allowing to modify the column which is part of foreign key constraint can lead to refusal of TRUNCATE TABLE, OPTIMIZE TABLE later. So it make sense to block the column modify operation when foreign key is involved irrespective of foreign_key_check variable. Correct way to modify the charset of the column when fk is involved: SET foreign_key_checks=OFF; ALTER TABLE child DROP FOREIGN KEY fk, MODIFY m VARCHAR(200) CHARSET utf8mb4; ALTER TABLE parent MODIFY m VARCHAR(200) CHARSET utf8mb4; ALTER TABLE child ADD CONSTRAINT FOREIGN KEY (m) REFERENCES PARENT(m); SET foreign_key_checks=ON; fk_check_column_changes(): Remove the FOREIGN_KEY_CHECKS while checking the column change for foreign key constraint. This is the partial revert of commit 5f1f2fc and it changes the behaviour of copy alter algorithm ha_innobase::prepare_inplace_alter_table(): Find the modified column and check whether it is part of existing and newly added foreign key constraint.
- Loading branch information
1 parent
423c28f
commit 5f09b53
Showing
8 changed files
with
298 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# | ||
# MDEV-31086 MODIFY COLUMN can break FK constraints, and | ||
# lead to unrestorable dumps | ||
# | ||
CREATE TABLE t1( | ||
id SERIAL, | ||
msg VARCHAR(100) CHARACTER SET utf8mb3, | ||
KEY(msg))ENGINE=InnoDB; | ||
CREATE TABLE t2( | ||
id SERIAL, | ||
msg varchar(100) CHARACTER SET utf8mb4, | ||
CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg))ENGINE=InnoDB; | ||
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") | ||
CREATE TABLE t2( | ||
id SERIAL, | ||
msg varchar(100) CHARACTER SET utf8mb3, | ||
msg_1 varchar(100) CHARACTER SET utf8mb3, | ||
INDEX (msg_1), | ||
INDEX (msg), | ||
CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg) | ||
ON DELETE CASCADE)ENGINE=InnoDB; | ||
SET FOREIGN_KEY_CHECKS=1; | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=INPLACE; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(400) character set utf8mb3, ALGORITHM=INPLACE; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' | ||
SET FOREIGN_KEY_CHECKS=1; | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY | ||
SET FOREIGN_KEY_CHECKS=1; | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try ALGORITHM=COPY | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(200) CHARACTER SET utf8mb3, ALGORITHM=INPLACE; | ||
ERROR HY000: Cannot change column 'msg_1': used in a foreign key constraint 'test/t2_ibfk_0' | ||
SET FOREIGN_KEY_CHECKS=1; | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=INPLACE; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' of table 'test/t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(400) CHARSET utf8mb3, ALGORITHM=INPLACE; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' of table 'test/t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; | ||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t2 DROP FOREIGN KEY fk_t1, MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY (msg) REFERENCES t1(msg), aLGORITHM=INPLACE; | ||
SET FOREIGN_KEY_CHECKS=1; | ||
DROP TABLE t2, t1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
--source include/have_innodb.inc | ||
--echo # | ||
--echo # MDEV-31086 MODIFY COLUMN can break FK constraints, and | ||
--echo # lead to unrestorable dumps | ||
--echo # | ||
CREATE TABLE t1( | ||
id SERIAL, | ||
msg VARCHAR(100) CHARACTER SET utf8mb3, | ||
KEY(msg))ENGINE=InnoDB; | ||
|
||
--error ER_CANT_CREATE_TABLE | ||
CREATE TABLE t2( | ||
id SERIAL, | ||
msg varchar(100) CHARACTER SET utf8mb4, | ||
CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg))ENGINE=InnoDB; | ||
|
||
CREATE TABLE t2( | ||
id SERIAL, | ||
msg varchar(100) CHARACTER SET utf8mb3, | ||
msg_1 varchar(100) CHARACTER SET utf8mb3, | ||
INDEX (msg_1), | ||
INDEX (msg), | ||
CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg) | ||
ON DELETE CASCADE)ENGINE=InnoDB; | ||
|
||
# Changing column used in FK constraint | ||
SET FOREIGN_KEY_CHECKS=1; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=INPLACE; | ||
|
||
SET FOREIGN_KEY_CHECKS=0; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(400) character set utf8mb3, ALGORITHM=INPLACE; | ||
|
||
# Changing column charset used in FK constraint | ||
SET FOREIGN_KEY_CHECKS=1; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
|
||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
|
||
SET FOREIGN_KEY_CHECKS=0; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=COPY; | ||
|
||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=INPLACE; | ||
|
||
# Modify the column in the newly added foreign constraint | ||
SET FOREIGN_KEY_CHECKS=1; | ||
--error ER_CANT_CREATE_TABLE | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
|
||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
|
||
|
||
SET FOREIGN_KEY_CHECKS=0; | ||
--error ER_CANT_CREATE_TABLE | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; | ||
|
||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; | ||
|
||
--error ER_FK_COLUMN_CANNOT_CHANGE | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(200) CHARACTER SET utf8mb3, ALGORITHM=INPLACE; | ||
|
||
# Change referenced table column | ||
SET FOREIGN_KEY_CHECKS=1; | ||
# Change referenced column length | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=INPLACE; | ||
# Change referenced column character set | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; | ||
|
||
SET FOREIGN_KEY_CHECKS=0; | ||
# Change referenced column length | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(400) CHARSET utf8mb3, ALGORITHM=INPLACE; | ||
|
||
# Change referenced column character set | ||
--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; | ||
|
||
# Correct way to change character set in foreign key constraint | ||
SET FOREIGN_KEY_CHECKS=0; | ||
ALTER TABLE t2 DROP FOREIGN KEY fk_t1, MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; | ||
ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY (msg) REFERENCES t1(msg), aLGORITHM=INPLACE; | ||
SET FOREIGN_KEY_CHECKS=1; | ||
|
||
DROP TABLE t2, t1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.