Bug #5574 ALTER TABLE of InnoDB table causes data dictionary problem
Submitted: 14 Sep 2004 16:58 Modified: 8 Apr 2005 21:00
Reporter: Paul Dubois Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:4.0.21/4.1.5 (at least) OS:Any (all)
Assigned to: Marko Mäkelä

[14 Sep 2004 16:58] Paul Dubois
Description:
I am seeing an InnoDB problem under these conditions:

- Create a table that contains foreign key constraints.

- Use ALTER TABLE to change the table to a MyISAM table.
(Why am I doing this? you ask.  I was trying to see if MySQL
would allow this operation or deny it.)  This succeeds,
although of course the foreign key information is lost from
the table definition.

- Drop the table.

- Try to recreate the table using its original definition as
an InnoDB table.  This fails with an error that the constraint
name already exists:

ERROR 1005 at line 19: Can't create table './test/child.frm' (errno: 121)

SHOW INNODB STATUS indicates this:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
040914 11:13:16 Error in foreign key constraint creation for table `test/child`.
A foreign key constraint of name `test/child_ibfk_1`
already exists.  (Note that internally InnoDB adds 'databasename/'
in front of the user-defined constraint name).

This occurs in 4.0.21 and 4.1.5.  (Haven't tried 5.0.x)

A script that demonstrates the problem is included below.  I find that I can make
the error go away in two ways:

- Drop and recreate the InnoDB tablespace.  (The drastic solution.)
- Add "CONSTRAINT some_name" to the front of the foreign key definition.
This doesn't really "solve" the problem, though, because the constraint
is still recorded in the data dictionary.

How to repeat:
DROP TABLE IF EXISTS parent;
CREATE TABLE parent
(
    parent_id   INT UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (parent_id)
) ENGINE = InnoDB;

DROP TABLE IF EXISTS child;
CREATE TABLE child
(
    parent_id   INT UNSIGNED NOT NULL,
    PRIMARY KEY (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent (parent_id)
) ENGINE = InnoDB;

ALTER TABLE child ENGINE = MyISAM;

DROP TABLE IF EXISTS child;
CREATE TABLE child
(
    parent_id   INT UNSIGNED NOT NULL,
    PRIMARY KEY (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent (parent_id)
) ENGINE = InnoDB;
[16 Sep 2004 13:42] Victoria Reznichenko
Verified on the latest Bk 4.0/4.1/5.0 trees.
[7 Apr 2005 0:38] Timothy Smith
Verified also on Windows XP & FreeBSD, 4.1.11  -- Timothy
[7 Apr 2005 5:24] Heikki Tuuri
Marko,

please prevent ALTER to MyISAM if the table is involved in FOREIGN KEY constraints. The ALTER confuses InnoDB's internal data dictionary.

Regards,

Heikki
[7 Apr 2005 10:03] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/23747
[7 Apr 2005 10:17] Marko Mäkelä
I've committed a fix that prevents ALTER TABLE from changing the storage engine from InnoDB if there are any foreign key constraints attached to the table.
[8 Apr 2005 21:00] Marko Mäkelä
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

The bug will be fixed in 4.1.12 and 5.0.5 or 5.0.4.
[19 May 2005 23:26] Mark Junker
Hmm ... it seems that there is a change between 4.1.8-nt and 4.1.12-nt. It seems that a foreign key name must be (at least) unique across all tables of a single database. This restriction didn't exist in 4.1.8.

Regards,
Mark
[23 May 2005 13:24] Marko Mäkelä
Mark,
To my knowledge, InnoDB has always enforced <database_name>+<key_name> to be unique. If you can prove this false, please submit the test case. Please note that MySQL silently ignores foreign keys and TYPE=InnoDB or ENGINE=InnoDB if the InnoDB storage engine is not available. It's best to check the SHOW CREATE TABLE output.