[MDEV-17187] table doesn't exist in engine after ALTER other tables with CONSTRAINTs Created: 2018-09-13 Updated: 2022-04-19 Resolved: 2019-08-21 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Data Definition - Alter Table, Storage Engine - InnoDB |
| Affects Version/s: | 5.5, 10.0, 10.1, 10.2.11, 10.2, 10.3, 10.4 |
| Fix Version/s: | 10.2.27, 10.3.18, 10.4.8 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Benjamin Zwittnig | Assignee: | Marko Mäkelä |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | affects-tests, upstream | ||
| Environment: |
CentOS Linux release 7.5.1804 (Core) |
||
| Issue Links: |
|
||||||||||||||||||||||||||||||||
| Description |
|
After ALTER of several tables (few of them had CONSTRAINs to a problematic table) a table 'vanished' from server.
it is however visible in table inventory (show tables). During ALTER statements foreign_key_checks was set to OFF. If I disable foreign_key_checks table appears again and it is visible after enabling foreign_key_checks. It seems this affect 'global' variable. After the server restart the table is 'invisible' again (with the same error as described above).
|
| Comments |
| Comment by Alice Sherepa [ 2018-09-13 ] | ||||||||||||||||||||||||
|
Thanks for the report!
| ||||||||||||||||||||||||
| Comment by Benjamin Zwittnig [ 2018-09-14 ] | ||||||||||||||||||||||||
|
It seems that the problem is in CONSTRAINT definition. After ALTER of other tables CHARSETs in definitions of fields in CONSTRAINT are no more the same. If the CONSTRAINT is dropped re-creation of the same CONSTRAINT fails with:
Table definitions after ALTER statements:
| ||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2019-01-13 ] | ||||||||||||||||||||||||
|
For Alice's test case above, the error log after restart for 10.2+ says
For 10.0 and 10.1, it contains an extra line:
No errors or warnings before restart. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-01-31 ] | ||||||||||||||||||||||||
|
I think that a sane fix of this would be to allow ha_innobase::open(), but refuse any modifications of the table data unless foreign_key_checks=0. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-01-31 ] | ||||||||||||||||||||||||
|
I tried an initial patch that removes DICT_ERR_IGNORE_FK_NOKEY. It turns out that we would have to implement an additional check in ha_innobase::create() and possibly ha_innobase::prepare_inplace_alter_table():
Also, if we remove the check from ha_innobase::open(), we must report errors on DML when foreign_key_checks are enabled and we find out that dict_foreign_t::referenced_index or dict_foreign_t::foreign_index is NULL. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-08-20 ] | ||||||||||||||||||||||||
|
It turns out that the MySQL 5.7.5 fix of removing a condition from ha_innobase::prepare_inplace_alter_table() was omitted when the InnoDB changes from MySQL 5.7.9 were applied to MariaDB 10.2.2. I think that it is best to remove the check from ha_innobase::open() and adjust the other code accordingly. If we fail to do that, users who have already dropped the indexes that are needed for enforcing FOREIGN KEY constraints would seem to have no way to regain access to the table. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-08-20 ] | ||||||||||||||||||||||||
|
The observation in the Description is explained by the fact that the function ha_innobase::open() allows the table to be opened when foreign_key_checks=0:
I will try to remove this special case, and implement the check for missing indexes when DML operations would access the indexes for enforcing FOREIGN KEY constraints. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-08-20 ] | ||||||||||||||||||||||||
|
I am working on a fix that replaces some use of DICT_ERR_IGNORE_NONE with DICT_ERR_IGNORE_FK_NOKEY, so that most of the time, we would allow access to tables even when some underlying indexes for FOREIGN KEY are missing. All existing tests pass with that, but I think that I must write an additional test where DML would encounter the missing index when trying to enforce a FOREIGN KEY constraint. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-08-20 ] | ||||||||||||||||||||||||
|
It turns out that the function row_ins_check_foreign_constraint(), which gets invoked when deleting from the parent table, was silently ignoring the constraint when the index is missing from the child table (the one with the CONSTRAINT…FOREIGN KEY…REFERENCES clause). Even after fixing that, I was still having the problem that an INSERT into the child table is being accepted. I fixed it so that such DELETE and INSERT will be rejected with foreign_key_checks=1 and accepted with foreign_key_checks=0. | ||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-08-20 ] | ||||||||||||||||||||||||
|
Please review the 3 commits at bb-10.2-marko, on top of 10.2. |