数据库FK约束与程序化FK约束

时间:2013-12-25 21:21:44

标签: database database-design

虽然我的目标是MySQL / PHP,但为了我的问题,我想将它通常应用于任何与现代编程语言结合使用的关系数据库。另一个假设是语言正在利用现代框架,在某种程度上,它会隐式处理外键约束或有明确的方法。

我的问题:

  • 在数据库本身创建FK约束的优点和缺点是什么,而不是在应用程序级别管理它们?

  • 从设计的角度来看,它们是否应该一起使用,还是会引起冲突?

  • 如果它们不能一起使用,那么对于使用哪种方法,什么被认为是“最佳做法”?

注意:这是一个设计理论问题。由于可用于满足实现的各种技术,我对实现的任何细节都不感兴趣。

3 个答案:

答案 0 :(得分:2)

  

在数据库本身创建FK约束的优点和缺点是什么,而不是在应用程序级别管理它们?

并发环境中,在应用程序代码中实现参照完整性非常困难,因此 正确且性能良好。

除非您非常小心地使用锁定,否则您可以接受竞争条件,例如:

  • 想象一下,父表中当前有一行,而子项中没有相应的行。
  • 事务T1在子表中插入一行,但尚未提交。它可以这样做,因为父表中有相应的行。
  • 事务T2删除父行。它可以做到这一点,因为从它的角度来看没有子行 (T1还没有提交)。
  • T1和T2提交。
  • 此时,您有一个没有父级的子行(即损坏的引用完整性)。

要解决这个问题,您可以从两个事务中锁定父行,但与DBMS本身实现的高度优化的FK相比,这可能性能较差。

最重要的是,所有您的客户必须遵守相同的“锁定协议”(一个行为不端的客户端足以破坏数据)。如果您有多个级别的嵌套FK或菱形FK,复杂性会迅速提升。即使您在触发器中实现参照完整性,您只能解决“一个行为不端的客户端”问题,但其余的仍然存在。

数据库级FK的另一个好处是它们通常支持引用操作,例如ON DELETE CASCADE。所有这些都是简单的自我记录,而不像在应用程序代码中隐藏的引用完整性。

  

从设计的角度来看,它们是否应该一起使用,还是会导致冲突?

您应始终使用数据库级FK。您也可以使用应用程序级别“预检查”,如果这有利于您的用户体验(即您不想等到实际的INSERT / UPDATE / DELETE警告用户),但您应始终编写代码,就好像INSERT /即使您的应用程序级别检查已通过,UPDATE / DELETE也可能失败。

  

如果它们不能一起使用,那么在使用哪种方法时被视为“最佳实践”?

正如我所说,总是使用数据库级别的FK。 (可选),您也可以在它们的“顶部”使用应用程序级别的FK。


另请参阅:Sql - Indirect Foreign Key

答案 1 :(得分:0)

您对数据库设计和外键概念的熟悉程度如何? FK是一个表中的一列,用于标识另一个表中的行。 (我很确定你已经知道了。)因此FK约束是DB中存在的东西,而不是应用程序中存在的东西。在应用程序中管理FK约束需要手动编码DB中已有的功能。那你为什么要做那些体力劳动呢?由于所有额外的手动编码,DB /应用程序交互和开发也更加困难。

最佳实践IMHO将使用这些工具来创建它们。 DB负责FK的参照完整性,应用程序不需要关注DB的内部功能。但是,如果参考完整性是您主要关注的问题,并且您使用的是MySQL和不支持FK constraints的MyISAM引擎,那么您必须在应用程序中进行一些手动检查(或者使用我不熟悉的数据库触发器)用)。请记住,当您在应用程序中执行所有类型的检查时,您仍然必须访问数据库,因此您使用的资源比数据库可以处理参照完整性检查所需的资源多。 (当然,简单的解决方案是使用InnoDB engine开始,但在此答案过于以产品为导向之前我会停在这里。

因此让DB处理FK约束的一些优点是:

  1. 你不必考虑它。
  2. 您不必手动编写任何额外的代码。
  3. 应用程序使用的资源更少,代码更少,因此......
  4. ...维护和开发DB和应用程序要容易得多(例如,应用程序开发人员不需要如此深入地理解面向数据库的概念和功能,让DB专家做FK等思考。 ..)。

答案 2 :(得分:0)

  

在数据库中创建FK约束的优缺点是什么?   本身而不是在应用程序级别管理它们?

使用db-enforced FK的一些优点:

  1. 从代码中分离出schmea。

  2. 缩小应用程序代码

  3. 程序员没有机会搞乱FK规则。

  4. 强制与db集成的其他应用程序遵循fk规则。

  5. 使用db强制FK的一些缺点。

    1. 如果您有特殊情况,不容易破解

    2. 如果数据无效,则可能会引发错误。应编写应用程序以优雅地处理错误,例如那些错误(特别是批处理错误)。

    3. 必须仔细定义和编码具有参照完整性规则的FK定义。您不希望在线级联删除1000000行。

    4. 它们会导致隐式检查,即使您不希望发生检查,因为您知道父行必须存在。这可能对性能产生微不足道的影响。在批量加载和OLAP / Data Warehouse系统中加载大量数据时,性能是一个问题。使用特殊加载工具,并且在加载期间通常禁用诸如数据库强制FK之类的约束。

    5.   

      从设计的角度来看,它们是否应该一起使用或   会导致冲突吗?

      你可以将它们放在一起是有原因的。正如我之前提到的,您可能在数据中有特殊情况,无法为其定义FK。此外,在某些情况下,例如FK之间无法处理的表之间的多对多自引用关系(至少对于某些数据库引擎)。