[MDEV-31086] MODIFY COLUMN can break FK constraints, and lead to unrestorable dumps Created: 2023-04-19 Updated: 2024-01-05 Resolved: 2023-06-27 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Affects Version/s: | 10.11.1, 10.6.12, 10.8.7, 10.9.5, 10.10.3, 10.7 |
| Fix Version/s: | 10.4.31, 10.5.22, 10.6.15, 10.9.8, 10.10.6, 10.11.5, 11.0.3 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Hartmut Holzgraefe | Assignee: | Thirunarayanan Balathandayuthapani |
| Resolution: | Fixed | Votes: | 2 |
| Labels: | foreign-keys | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description |
|
When creating a foreign key constraint the referenced columns on both sides need to have the same data types, including same character set. E.g.
will fail with "Foreign key constraint is incorrectly formed" due to the mix of utf8mb3 and utf8mb4. Even with foreign_key_checks=OFF this will still not work. Changing the character set to "utf8mb3" I can create the 2nd table now, as expected:
Now the problem is that starting with 10.6 I can change the character set "under the hood" without getting an error at all, regardless of foreign_key_checks being ON or OFF:
With 10.5 and earlier the situation is a bit better, the MODIFY COLUMN will lead to Cannot change column 'msg': used in a foreign key constraint 'fk_t1' when foreign_key_checks are ON, but will succeed when checks are OFF; unlike the CREATE TABLE above that will fail regardless of checks being ON or OFF. And with that we now have a table with a broken foreign key constraint, and a schema that we can dump with mysqldump, but not restore as the dump now contains a CREATE TABLE statement with a FK CONSTRAINT that will lead to an Foreign key constraint is incorrectly formed error even though mysqldump takes care to turn off foreign_key_checks for the duration of a restore. So two things need to be fixed here IMHO:
|
| Comments |
| Comment by Hartmut Holzgraefe [ 2023-04-19 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MariaDB 10.5 and earlier correctly complain about "Foreign key constraint is incorrectly formed" on the MODIFY COLUMN attempt, it is only 10.6 and later that allow for this change to happen, and so to end up with an unrestorable dump | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Hartmut Holzgraefe [ 2023-04-20 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I updated the description above a bit as there are actually two problems:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2023-04-24 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
That MODIFY COLUMN breaks an FK constraint under foreign_key_checks=ON in 10.6 is certainly a bug. Behavior under foreign_key_checks=OFF — not necessarily | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2023-04-24 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think that this can be fixed by adding FOREIGN KEY checks to ha_innobase::can_convert_nocopy() or its callees. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2023-05-02 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think we need to allow to change the column data type, column length and charset when foreign_key_checks is disabled. User
I had discussion with pandi.gurusamy about stored procedure | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2023-05-09 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think that we must extend the test a little more and improve the check a little. I do not immediately see any problem if a FOREIGN KEY connected VARCHAR column is being extended, but the current fix would be prohibiting that. When writing the test, please note that extending a VARCHAR from up to 127 bytes to at least 127 bytes can only be done instantly if ROW_FORMAT=REDUNDANT. See | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2023-05-30 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
As far as I understand, the first CREATE TABLE example in the Description would fail even if foreign_key_checks=OFF. To be consistent with that, a corresponding ALTER TABLE must fail too, regardless of whether ALGORITHM=COPY is being used. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2023-05-30 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It turns out in the SQL layer, the function fk_check_column_changes() would intentionally cause ALTER TABLE…ALGORITHM=COPY to ignore invalid foreign key constraints if foreign_key_checks=OFF. This would seem to be misguided, because a subsequent TRUNCATE TABLE or OPTIMIZE TABLE (if alter_algorithm=copy) and possibly ALTER TABLE…FORCE, ALGORITHM=COPY would be refused on the table. thiru, please fill in the details. When foreign_key_checks=OFF, I think that it is reasonable to allow CREATE TABLE or ALTER TABLE to create FOREIGN KEY constraints that refer to non-existing tables. But I do not see the usefulness of allowing the creation of totally invalid foreign key constraints, that is, when columns are of incompatible type or use incompatible character encodings or collations. I think a good guideline is that the output of SHOW CREATE TABLE after any number of DDL operations will be a valid CREATE TABLE statement if foreign_key_checks=OFF. If someone wants to change the collation or encoding of a column that is connected to a FOREIGN KEY constraint, that can be done with 3 ALTER TABLE statements, something like this (untested SQL):
Disabling the checks will allow the ADD CONSTRAINT to be instantaneous; see also MDEV-16356. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2023-05-30 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2023-06-02 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thank you, it looks good. Once you have addressed my minor comments and this has passed testing, this will require another review of the change to fk_check_column_changes() (to make ALTER TABLE…ALGORITHM=COPY stricter). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2023-06-20 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
thiru, server changes in f1746ad6dd are ok |