MySQL 5.5 外键存在时外键约束失败

发布于 2024-10-30 21:40:06 字数 6798 浏览 8 评论 0原文

刚刚在 mac os x 10.6 上安装了 MySQL 5.5,并且在许多表上遇到了一个奇怪的问题。下面是一个例子。由于外键约束,插入行在不应该失败的情况下会失败。它引用的外键确实存在。有什么想法吗?

mysql> show create table Language;
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language | CREATE TABLE `Language` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Code` varchar(2) NOT NULL,
  `Name` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Variant` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Country_Id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Code` (`Code`,`Country_Id`,`Variant`),
  KEY `FKA3ACF7789C1796EB` (`Country_Id`),
  CONSTRAINT `FKA3ACF7789C1796EB` FOREIGN KEY (`Country_Id`) REFERENCES `Country` (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show create table Language_Phrases;
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table            | Create Table                                                                                                                                                                                                                                                                                                                                                    |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language_Phrases | CREATE TABLE `Language_Phrases` (
  `Language_Id` int(11) NOT NULL,
  `Phrase` varchar(255) DEFAULT NULL,
  `Label` varchar(255) NOT NULL,
  PRIMARY KEY (`Language_Id`,`Label`),
  KEY `FK8B4876F3AEC1DBE9` (`Language_Id`),
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from Language;
+----+------+----------+---------+------------+
| Id | Code | Name     | Variant | Country_Id |
+----+------+----------+---------+------------+
|  1 | en   | English  |         |        235 |
|  2 | ro   | Romanian |         |        181 |
+----+------+----------+---------+------------+
2 rows in set (0.00 sec)

mysql> select * from Language_Phrases;
Empty set (0.00 sec)

mysql> INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`dev`.`language_phrases`, CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`))
mysql> 

更新:在多次删除并重新创建数据库后,我在上面的插入失败后执行了show engine innodb status,并得到了这个令人惊讶的结果。找不到父语言表!这看起来很奇怪......有什么想法吗?

------------------------
LATEST FOREIGN KEY ERROR
------------------------
110406  9:55:49 Transaction:
TRANSACTION CA3B, ACTIVE 0 sec, OS thread id 4494462976 inserting
mysql tables in use 1, locked 1
1 lock struct(s), heap size 376, 0 row lock(s)
MySQL thread id 25, query id 50720 localhost root update
INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase')
Foreign key constraint fails for table `dev`.`language_phrases`:
,
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
Trying to add to index `PRIMARY` tuple:
DATA TUPLE: 5 fields;
 0: len 4; hex 80000001; asc     ;;
 1: len 17; hex 747970654d69736d617463682e79656172; asc exampleLabel;;
 2: len 6; hex 00000000ca3b; asc      ;;;
 3: len 7; hex 00000000000000; asc        ;;
 4: len 21; hex 59656172206d7573742062652061206e756d626572; asc Some phrase;;

But the parent table `dev`.`Language`
or its .ibd file does not currently exist!

更新 2:事实证明,这只是 MySQL 中的一个巨大错误。显然最新版本的 MySQL 在 mac os X 10.6 下不能完全工作(也许早期版本也是如此?)。降级到 5.5.8 似乎有效。极其令人惊讶。

Just installed MySQL 5.5 on mac os x 10.6 and am having a strange issue on many tables. Below is an example. Inserting a row fails with a foreign key constraint when it shouldn't. The foreign key it references does exist. Any ideas?

mysql> show create table Language;
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language | CREATE TABLE `Language` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Code` varchar(2) NOT NULL,
  `Name` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Variant` varchar(63) CHARACTER SET utf8 DEFAULT NULL,
  `Country_Id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Code` (`Code`,`Country_Id`,`Variant`),
  KEY `FKA3ACF7789C1796EB` (`Country_Id`),
  CONSTRAINT `FKA3ACF7789C1796EB` FOREIGN KEY (`Country_Id`) REFERENCES `Country` (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 |
+----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show create table Language_Phrases;
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table            | Create Table                                                                                                                                                                                                                                                                                                                                                    |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Language_Phrases | CREATE TABLE `Language_Phrases` (
  `Language_Id` int(11) NOT NULL,
  `Phrase` varchar(255) DEFAULT NULL,
  `Label` varchar(255) NOT NULL,
  PRIMARY KEY (`Language_Id`,`Label`),
  KEY `FK8B4876F3AEC1DBE9` (`Language_Id`),
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from Language;
+----+------+----------+---------+------------+
| Id | Code | Name     | Variant | Country_Id |
+----+------+----------+---------+------------+
|  1 | en   | English  |         |        235 |
|  2 | ro   | Romanian |         |        181 |
+----+------+----------+---------+------------+
2 rows in set (0.00 sec)

mysql> select * from Language_Phrases;
Empty set (0.00 sec)

mysql> INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`dev`.`language_phrases`, CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`))
mysql> 

UPDATE: After dropping and recreating the database several times, I did a show engine innodb status after the failing insert above and got this surprising result. The parent Language table is not found! This seems very strange... any ideas?

------------------------
LATEST FOREIGN KEY ERROR
------------------------
110406  9:55:49 Transaction:
TRANSACTION CA3B, ACTIVE 0 sec, OS thread id 4494462976 inserting
mysql tables in use 1, locked 1
1 lock struct(s), heap size 376, 0 row lock(s)
MySQL thread id 25, query id 50720 localhost root update
INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase')
Foreign key constraint fails for table `dev`.`language_phrases`:
,
  CONSTRAINT `FK8B4876F3AEC1DBE9` FOREIGN KEY (`Language_Id`) REFERENCES `Language` (`Id`)
Trying to add to index `PRIMARY` tuple:
DATA TUPLE: 5 fields;
 0: len 4; hex 80000001; asc     ;;
 1: len 17; hex 747970654d69736d617463682e79656172; asc exampleLabel;;
 2: len 6; hex 00000000ca3b; asc      ;;;
 3: len 7; hex 00000000000000; asc        ;;
 4: len 21; hex 59656172206d7573742062652061206e756d626572; asc Some phrase;;

But the parent table `dev`.`Language`
or its .ibd file does not currently exist!

UPDATE 2: It turns out this is simply a massive bug in MySQL. Apparently the latest versions of MySQL do not work fully under mac os X 10.6 (maybe earlier versions too?). Downgrading to 5.5.8 seems to work. Extremely surprising.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

猫烠⑼条掵仅有一顆心 2024-11-06 21:40:06

这似乎是自 Mac OS X 上的 MySQL 5.5.9 以来引入的一个错误:
http://bugs.mysql.com/bug.php?id=60309

它被标记为已修复5.5.13(5 月 31 日发布)中并在发行说明中提到:
http://dev.mysql.com/doc/refman/5.5/ en/news-5-5-13.html

另外,错误报告中列出了一个解决方法,我已在 5.5.10 上验证并复制如下:

[20 Mar 11:29] Harald Neiss

I also received a new MBP and reinstalled MySQL (mysql-5.5.10-osx10.6-x86_64). Finally I
came across the same problem as described above. So here is the query result and what I
did to solve it.

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 2     |
+------------------------+-------+
2 rows in set (0.00 sec)

Dropped database, created the file /etc/my.cnf with the following content:

[mysqld]
lower_case_table_names=1

Restarted the MySQL daemon and repeated the query:

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 1     |
+------------------------+-------+
2 rows in set (0.00 sec)

I recreated the tables and everything works fine.

This does appear to be a bug introduced since MySQL 5.5.9 on Mac OS X:
http://bugs.mysql.com/bug.php?id=60309

It is marked as fixed in 5.5.13 (released May 31) and mentioned in the release notes:
http://dev.mysql.com/doc/refman/5.5/en/news-5-5-13.html

Alternatively, there is a workaround listed in the bug report that I've verified on 5.5.10 and reproduced below:

[20 Mar 11:29] Harald Neiss

I also received a new MBP and reinstalled MySQL (mysql-5.5.10-osx10.6-x86_64). Finally I
came across the same problem as described above. So here is the query result and what I
did to solve it.

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 2     |
+------------------------+-------+
2 rows in set (0.00 sec)

Dropped database, created the file /etc/my.cnf with the following content:

[mysqld]
lower_case_table_names=1

Restarted the MySQL daemon and repeated the query:

mysql> show variables like 'lower%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_file_system | ON    |
| lower_case_table_names | 1     |
+------------------------+-------+
2 rows in set (0.00 sec)

I recreated the tables and everything works fine.

冷默言语 2024-11-06 21:40:06

恕我直言,这并不奇怪。我在 MySQL 中发现了许多错误。例如,使用“WHERE some_tinyint_column = 0”等 where 子句运行查询将不会产生任何数据,但将子句重写为“WHERE (NOT some_tinyint_column = 1)”会产生结果。经过一番研究,我发现这是一个应该已修复的错误,但在我使用的版本中,该错误仍然存​​在。

结论:当某些东西在 MySQL 中完全没有意义时,我通常会认为它是一个错误,并开始沿着这些思路研究信息。

Not surprising IMHO. I have found numerous bugs in MySQL. For example running queries with where clauses such as "WHERE some_tinyint_column = 0" would produce no data when it should, but rewriting the clause as "WHERE (NOT some_tinyint_column = 1)" produces results. After some research I found that it was a bug that was supposed to have been fixed, but in the release I was using, the bug was still there.

Conclusion: when something makes absolutely no sense in MySQL, I usually find it safe to assume it's a bug and start researching for info along those lines.

心碎的声音 2024-11-06 21:40:06

我也面临同样的问题,但没有找到任何解决方案来解决我的问题。因此,由于多种原因可能会出现此问题。我只是试图将尽可能多的原因和解决方案放在一个地方,并提供帮助我解决此问题的修复程序。我希望这对将来的人有帮助。

1) 由 Penfold 提供 - 表名称区分大小写
2) 父子表中引擎不匹配
3) 父子表中的字符集不匹配
4) Parent(Id) 和 Child(Patent_Id : 两者必须具有完全相同的数据类型(也有符号/无符号)
5) InnoDB 丢失表但表存在 - 请在此处找到解决方案

SQL 查询(显示引擎 InnoDB 状态)给出此错误(其 .ibd 文件当前不存在!)
块引用

6) 很少有旧版本的 mysql 有这个 bug。Bug#60196, Bug#60309
7)这对我有用(如果上面的一切看起来都很好,你可能需要这个)-从子表中删除外键并再次添加约束。如果也失败,则删除父表并重新创建它,在此之前您需要从所有子表中删除外键。这是最后可能发生的事情。

进一步阅读:

https://dev.mysql .com/doc/refman/8.0/en/server-system-variables.html#sysvar_lower_case_table_names

I was also facing the same issue and did not find any solution which solves my issue. So this issue can occur due to many reasons. I am just trying to put as many of these reasons and solutions at one place and also putting the fix which helped me to resolve this. I hope this will help someone in future.

1) Provided by Penfold - case sensitivity of table names
2) Engine mismatch in Parent and Child Table
3) Charset mismatch in Parent and Child Table
4) Parent(Id) and Child(Patent_Id : both must have exactly same data types (Also Signed/Unsigned)
5) InnoDB lost table but table exists - Please find solution here

SQL Query (show engine InnoDB status) gives this error (its .ibd file does not currently exist!)
Blockquote

6) Few older versions of mysql has this bug.Bug#60196, Bug#60309
7) This works for me (if everything above seems fine, you probably needs this)- Dropping the foreign key from Child Table and Add Constraint again. If it also fails then drop parent table and create it again, before this you need to drop foreign key from all the Child Tables. This one is last possible thing.

Further Read :

https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_lower_case_table_names

就此别过 2024-11-06 21:40:06

检查 Language_Phrases (Language_Id)Language (Id) 的数字类型属性

两者都应该是UNSIGNED ZEROFILLSIGNED

check the Numeric Type Attributes of Language_Phrases (Language_Id) and Language (Id)

both should be either UNSIGNED ZEROFILL or SIGNED

抱猫软卧 2024-11-06 21:40:06

*mysql> INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', '一些短语');
错误 1452 (23000):无法添加或更新子行:...*

您尝试插入 1 作为 Language_Id,但表 Language 具有属性 AUTO_INCRMENT=3。在这种情况下,您应该使用 3 或更高。

*mysql> INSERT INTO Language_Phrases (Language_Id, Label, Phrase) VALUES (1, 'exampleLabel', 'Some phrase');
ERROR 1452 (23000): Cannot add or update a child row:...*

You are trying to insert 1 as Language_Id, but table Language has property AUTO_INCREMENT=3. In this case you should use 3 or higher.

自此以后,行同陌路 2024-11-06 21:40:06

我今天也犯了同样的错误。就我而言,我使用脚本重新创建了一些包含所有记录的表。

事实上,我已经意识到我的表之间的“引擎”类型不同:一个是 MyISAM,第二个(FK 的引用)是 InnoDB。我已将所有表更改为 InnoDB,现在一切正常。

该脚本将生成一个更新脚本文件(参考

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME -e "SELECT CONCAT('ALTER TABLE ', table_name, ' ENGINE=InnoDB;') AS sql_statements FROM information_schema.tables AS tb WHERE table_schema = database() AND ENGINE = 'MyISAM' AND TABLE_TYPE = 'BASE TABLE' ORDER BY table_name DESC;" > ./alter_InnoDb.sql

您必须删除“alter_InnoDb.sql”中包含文本“sql_statements”的第一行。

之后,您可以在数据库中执行脚本来纠正此错误:

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME < ./ alter_InnoDb.sql

I had the same error today. In my case, I've used a script to recreate a few tables with all their records.

In fact, I've realised that "Engine" type was different between my tables: one was MyISAM and the second one (the reference of the FK) was InnoDB. I've altered all my tables to InnoDB and now everything works fine.

This script will generate an update script file (Reference)

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME -e "SELECT CONCAT('ALTER TABLE ', table_name, ' ENGINE=InnoDB;') AS sql_statements FROM information_schema.tables AS tb WHERE table_schema = database() AND ENGINE = 'MyISAM' AND TABLE_TYPE = 'BASE TABLE' ORDER BY table_name DESC;" > ./alter_InnoDb.sql

You must remove the first line in "alter_InnoDb.sql", line containing the text "sql_statements".

After that, you can execute the script in your database to correct this error:

mysql -u DB_USER -pDB_PASSWORD --default-character-set=utf8  DATABASE_NAME < ./ alter_InnoDb.sql
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文