[MDEV-8845] Table disappear after modifying FK Created: 2015-09-25 Updated: 2016-12-15 Resolved: 2015-10-01 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB, Storage Engine - XtraDB |
| Affects Version/s: | 5.1.67, 5.2.14, 5.3.12, 5.5 |
| Fix Version/s: | 5.5.46 |
| Type: | Bug | Priority: | Major |
| Reporter: | Sam Grandjean | Assignee: | Jan Lindström (Inactive) |
| Resolution: | Done | Votes: | 0 |
| Labels: | upstream-fixed | ||
| Environment: |
Win 7 Pro SP1 64-bit |
||
| Issue Links: |
|
||||||||
| Sprint: | 10.1.8-4 | ||||||||
| Description |
| Comments |
| Comment by Elena Stepanova [ 2015-09-25 ] | ||||||||||||||||
|
It's an upstream bug https://bugs.mysql.com/bug.php?id=68148 which was fixed in 5.6.12 and thus in 10.0 before GA. Do you think there is a critical need to backport the fix into 5.5? | ||||||||||||||||
| Comment by Sam Grandjean [ 2015-09-25 ] | ||||||||||||||||
|
Our company is still on 5.5 branch. We think losing data by sending invalid queries should not happen at all. Since 5.5 branch is supported until 2017, backporting the fix is a necessity. | ||||||||||||||||
| Comment by Elena Stepanova [ 2015-09-25 ] | ||||||||||||||||
|
Please consider if it's possible to backport the fix from 5.6/10.0 to 5.5. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2015-09-30 ] | ||||||||||||||||
|
In MySQL 5.6 this was fixed on: commit b21b9953a710e8dfdd133eba942b1767fc0f5acd Bug#16208542 DROP INDEX ON A FOREIGN KEY COLUMN LEADS TO MISSING TABLE == Analysis == == Solution == A new enum type in dict_err_ignore_t called DICT_ERR_IGNORE_FK_NOKEY An error message can be found when open a table with missing fk indexes. rb#2308 is approved by Marko In my understanding the port to MySQL 5.5 has been done in: commit 7b66df16a1ca00084ee6336aaf50d32f914e625c Bug 16876388 - PLEASE BACKPORT BUG#16208542 TO 5.5 Straight forward backport. Approved by Jimmy, rb#2656 Both referenced numbers are not open to public but based on dates both should be already merged to MariaDB, notable is that both fixes do not contain test cases, thus I will create one to rest is the issue really fixed. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2015-09-30 ] | ||||||||||||||||
|
I did not see any disappearing tables while testing. Remember that optimize table is same as alter table ... engine=innodb; and you should not run that when foreign_key_checks=0 and table is still missing required index for fk. If you do execute optimize table, table name will be changed to internal name (see from data directory the name). You can get back that table with foreign_key_checks=0 and rename table. | ||||||||||||||||
| Comment by Elena Stepanova [ 2015-09-30 ] | ||||||||||||||||
|
This is a disappearance of the table. test_item was there, and then it was not. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2015-10-01 ] | ||||||||||||||||
|
Idea here is that you normally run your ALTER and other commands with FOREIGN_KEY_CHECKS=1 i.e. InnoDB will automatically make sure that you do not break table and database consistency. If user sets FOREIGN_KEY_CHECKS=0, it is indication that you know what you are doing. While this setting is disabled you may ALTER the table so that table is not consistent. This is by design, there are several clauses about this on documentation (and I do agree it is not exhaustive). If you make table not consistent e.g. by dropping the foreign key index, table is removed from the InnoDB tablespace cache. This is done because if you then set FOREIGN_KEY_CHECKS=1, this setting does not really immediately do any consistency checking. Thus, if table would be on tablespace cache, you could e.g. INSERT data to it and your database could be broken. So, if you do try to INSERT InnoDB tries to open that table, not found from cache so it is tried to load from data dictionary. Now that foreign key checks is enabled the table load will fail. I could change the server to refuse to drop foreign key index even when FOREIGN_KEY_CHECKS=0 (and I actually would prefer it to be like that, so that user must drop first the foreign key constraint and then index if needed) but that would make MariaDB and MySQL behave differently and (actual change is not big) not sure if that change is safe for GA product (current applications could already use this feature). | ||||||||||||||||
| Comment by Sam Grandjean [ 2015-10-01 ] | ||||||||||||||||
|
Thank you for your input, Jan. As stated by Elena, it would be nice not needing to know MySQL internals to handle this issue, but your explanation makes lot of sense. For those wondering how to recover table, you can use RENAME statement. Eg:
However this requires ALTER, DROP, CREATE, and INSERT privileges, and also knowing the table name on filesystem. | ||||||||||||||||
| Comment by Vadym Surzhyk [ 2016-11-18 ] | ||||||||||||||||
|
Mysql bug https://bugs.mysql.com/bug.php?id=68148 can be reproduced in Mariadb 10.0.28 and 10.1.19. Welcome to the MariaDB monitor. Commands end with ; or \g. mysql [localhost] {msandbox} (test) > CREATE TABLE ref_table2 (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB; mysql [localhost] {msandbox} (test) > CREATE TABLE `main` ( mysql [localhost] {msandbox} (test) > SET FOREIGN_KEY_CHECKS=0; mysql [localhost] {msandbox} (test) > DROP INDEX `idx_1` ON `main`; mysql [localhost] {msandbox} (test) > exit; And then after restart of Mariadb: mysql [localhost] {msandbox} (test) > SHOW CREATE TABLE main; In Mysql 5.7.16 the bug isn't reproducible because the server blocks the index dropping: Welcome to the MySQL monitor. Commands end with ; or \g. mysql [localhost] {msandbox} (test) > CREATE TABLE ref_table2 (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB; mysql [localhost] {msandbox} (test) > CREATE TABLE `main` ( mysql [localhost] {msandbox} (test) > SET FOREIGN_KEY_CHECKS=0; mysql [localhost] {msandbox} (test) > DROP INDEX `idx_1` ON `main`; | ||||||||||||||||
| Comment by Vadym Surzhyk [ 2016-12-12 ] | ||||||||||||||||
|
The problem isn't fixed. Look at the previous comment please. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2016-12-12 ] | ||||||||||||||||
|
This looks little bit different compared to original report as now you have added server restart. I will review current MySQL behavior and see if we can follow their solution. My original comment holds also here, set foreign_key_checks=0 should allow user temporally break foreign key constraints and if you do then it is user's responsibility to fix the situation as server does not enough information to always fix it. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2016-12-14 ] | ||||||||||||||||
|
You can use following to restore table in above case:
No need to know any internals. | ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2016-12-14 ] | ||||||||||||||||
|
Verified what MariaDB and MySQL do
| ||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2016-12-15 ] | ||||||||||||||||
|
I do not see here any reason to fix the current way in 5.5, 10.0, 10.1. Currently, MariaDB 10.2 does behave differently compared to MySQL 5.7, but in my opinion user should have a choice to drop a index needed in a foreign key constraint while foreign_key_checks=0. This is because setting foreign_key_checks=0 is indication that user want's to temporally do operations that can make foreign key constraints not consistent. If user has not fixed them consistent after setting foreign_key_checks=1 server does print errors on error log and there is a way to fix the situation. Thus, in my opinion works-as-designed. |