【问题标题】:MySQL: Foreign key constraints that exceed max depthMySQL:超过最大深度的外键约束
【发布时间】:2012-12-14 07:16:51
【问题描述】:

我在生产服务器上安装了MySQL Server 5.1.62。我每天都在监控 mysql 服务器的错误日志文件,突然我在错误日志文件中发现了以下错误。

InnoDB:无法删除/更新具有超过最大深度 250 的级联外键约束的行
请放弃过多的外来约束,然后重试

我有一个具有 主键 - 外键 关系的数据库结构,具有适当的更新/删除操作,如果父表中的数据被应用程序或手动(后端)删除,我需要删除子表的数据)。

我已经用谷歌搜索过这个问题,但找不到合适的解决方案。我该如何解决这个问题?

【问题讨论】:

  • 你能发布你的架构吗?我怀疑你的外键约束中有一个循环。您不必发布整个表格,只需发布​​外键设置中提到的列即可。
  • 我在这里同意@Barmar。您的数据库架构可能有一个循环外键约束,导致删除错误。我们需要看到 table+column 模式才能更有帮助。
  • 在您开始看到此错误消息之前发生了什么变化?
  • Deleting multiple rows from tbl_indentmaster 并且由于级联删除所有子表中的数据都被删除了所以我发现了这个错误
  • 我的意思不是那种改变。在您开始看到此错误消息之前,db 架构或服务器配置发生了什么变化?

标签: mysql foreign-keys sql-delete cascading-deletes


【解决方案1】:

看看这个链接 - Cascade Delete results in "Got error -1 from storage engine"。有一个建议。

另外,作为一种解决方案,您可以尝试不使用 ON DELETE CASCADE 选项,只需使用从某些表中删除记录的DELETE 语句(多表语法)。

【讨论】:

  • 我已经使用了 ON DELETE CASCADE,当我执行 DELETE Query 时出现错误。这不是我的问题的解决方案
  • 超出是当你有太多...这不能通过添加更多来解决
  • 我已经检查了该链接,但没有找到适合这种情况的确切解决方案
【解决方案2】:

模式图不是很有用,因为它没有显示任何级联声明。例如,如果删除应该从 tbl_indentmaster 级联到 tbl_tepdetails,但删除应该从 tbl_tepdetails 级联到 tbl_tepnoting,那么我预计某些删除会失败。 (但有不同的错误信息。)

如果有 是导致这种情况的循环引用约束,我希望它部分是由从 tbl_indentmaster 到 tbl_tepdetails 的级联引用引起的。您可能想尝试删除该外键约束以进行测试。在 tset sserver 上执行此操作,而不是在生产服务器上。

如果这突然开始,并且您的数据库之前正常工作,我会首先考虑

  • 从备份中恢复数据库,或
  • 从备份中恢复架构并重新加载当前数据,或者
  • 检出当前版本并重建数据库。 (你有database schema under version control,不是吗?)

我假设您没有良好的备份,并且您的架构不受版本控制。

您是否从一个好的数据库开始?运行mysqlcheck。仔细阅读该文档。在您拥有经过测试的良好备份之前,请勿--repair

假设你的数据库很好,级联删除应该在你的数据库中正常工作,并且你的谷歌技能很好,我认为你最好的开始

  • 在测试服务器上安装 MySQL 5.5 或 5.6,
  • 将您的数据库加载到该测试服务器上,然后
  • 看看您是否可以重现该特定错误。

要将数据库加载到测试服务器,请使用mysqldump 转储内容。不要在文件系统级别复制文件——其中一个或多个可能已损坏。

虽然这可能不能解决您的问题,但它可能会告诉您问题出在哪里。如果它工作正常,您就知道问题可能与服务器版本有关,并且可以通过版本升级来解决。

【讨论】:

  • 我已将 mysql 版本更新到 5.5,但我仍然面临同样的问题
  • 在我的架构设计中,所有的关系都是通过级联删除创建的。直到 mow 我没有从 db 中删除任何行但现在我想删除过去的数据所以我得到了这个错误
  • 您是否在测试服务器上删除了 tbl_indentmaster 和 tbl_tepdetails 之间的外键约束,然后尝试从 tbl_indentmaster 中删除行?
  • 如果我从数据库中删除约束,它将起作用。但我不能那样做。根据我的理解,由于超出约束深度而发生错误,就像我从 indentmaster 表中删除 50 行一样,它会自动从不同表中删除 1000 多行,因此它跨越了级联删除的深度
  • 你的理解是错误的;行数无关紧要。问题可能与您级联删除的表的数量有关。那是可能,因为你有一个循环引用。 (删除级联到它开始的表。)如果在您删除 tbl_indentmaster 和 tbl_tepdetails 之间的 FK 约束时它起作用,则放回 那个 约束,并删除 tbl_tepdetails 和 tbl_tepmapbidder 之间的 FK 约束。重复直到你找出问题,我预计这将是一个循环 FK 引用。
【解决方案3】:

我同意@Devart 和@Catcall 的原始答案,但我想在与 OP 交换一些 cmets 后添加一些内容。

首先,我已将架构图像表示减少为仅受tbl_indentmaster 上的DELETE 查询影响的表。

据我所知,此架构图中没有个循环外键引用。

此外,OP 运行了以下查询:

DELETE FROM tbl_indentmaster WHERE indentId IN (1,2,3,4,5,6,...,150,151,155,156,....)

要删除的行太多了。在进一步询问时,OP 声称该查询适用于 indentId 的较小子集。

由此我认为我们可以采取两种可能:

  1. MySQL 中存在一个错误(极不可能但可能),它会导致像您这样使用CASCADE DELETE 的大型查询失败。请注意,我建议 错误不是 [已发布][2] 的可能性。理想情况下,要删除的行数应该不重要。
  2. tbl_indentmaster 中有一个特定的 indentId 条目导致整个查询失败。

我建议您首先尝试诊断问题,考虑到第 (2) 点是真正的罪魁祸首。您可以将DELETE 查询分成更小的块并找到有问题的 id。

如果此脚本必须通过代码定期执行(在较大的应用程序中),那么您应该考虑在那里以较小的块执行查询(可能每个查询 15 个 id 是一个好的开始 IMO)。除了这样做之外,我还建议在日志文件中记录带有违规 id 的错误,以便您确切知道哪些条目失败了。

【讨论】:

  • 我已经把sata分成小块并删除了。我想找出这个错误的根本原因。我也认为这是mysql的局限性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
  • 2020-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多