虽然我的目标是MySQL / PHP,但为了我的问题,我想将它通常应用于任何与现代编程语言结合使用的关系数据库。另一个假设是语言正在利用现代框架,在某种程度上,它会隐式处理外键约束或有明确的方法。
我的问题:
在数据库本身创建FK约束的优点和缺点是什么,而不是在应用程序级别管理它们?
从设计的角度来看,它们是否应该一起使用,还是会引起冲突?
如果它们不能一起使用,那么对于使用哪种方法,什么被认为是“最佳做法”?
注意:这是一个设计理论问题。由于可用于满足实现的各种技术,我对实现的任何细节都不感兴趣。
答案 0 :(得分:2)
在数据库本身创建FK约束的优点和缺点是什么,而不是在应用程序级别管理它们?
在并发环境中,在应用程序代码中实现参照完整性非常困难,因此 正确且性能良好。
除非您非常小心地使用锁定,否则您可以接受竞争条件,例如:
要解决这个问题,您可以从两个事务中锁定父行,但与DBMS本身实现的高度优化的FK相比,这可能性能较差。
最重要的是,所有您的客户必须遵守相同的“锁定协议”(一个行为不端的客户端足以破坏数据)。如果您有多个级别的嵌套FK或菱形FK,复杂性会迅速提升。即使您在触发器中实现参照完整性,您只能解决“一个行为不端的客户端”问题,但其余的仍然存在。
数据库级FK的另一个好处是它们通常支持引用操作,例如ON DELETE CASCADE。所有这些都是简单的自我记录,而不像在应用程序代码中隐藏的引用完整性。
从设计的角度来看,它们是否应该一起使用,还是会导致冲突?
您应始终使用数据库级FK。您也可以使用应用程序级别“预检查”,如果这有利于您的用户体验(即您不想等到实际的INSERT / UPDATE / DELETE警告用户),但您应始终编写代码,就好像INSERT /即使您的应用程序级别检查已通过,UPDATE / DELETE也可能失败。
如果它们不能一起使用,那么在使用哪种方法时被视为“最佳实践”?
正如我所说,总是使用数据库级别的FK。 (可选),您也可以在它们的“顶部”使用应用程序级别的FK。
答案 1 :(得分:0)
您对数据库设计和外键概念的熟悉程度如何? FK是一个表中的一列,用于标识另一个表中的行。 (我很确定你已经知道了。)因此FK约束是DB中存在的东西,而不是应用程序中存在的东西。在应用程序中管理FK约束需要手动编码DB中已有的功能。那你为什么要做那些体力劳动呢?由于所有额外的手动编码,DB /应用程序交互和开发也更加困难。
最佳实践IMHO将使用这些工具来创建它们。 DB负责FK的参照完整性,应用程序不需要关注DB的内部功能。但是,如果参考完整性是您主要关注的问题,并且您使用的是MySQL和不支持FK constraints的MyISAM引擎,那么您必须在应用程序中进行一些手动检查(或者使用我不熟悉的数据库触发器)用)。请记住,当您在应用程序中执行所有类型的检查时,您仍然必须访问数据库,因此您使用的资源比数据库可以处理参照完整性检查所需的资源多。 (当然,简单的解决方案是使用InnoDB engine开始,但在此答案过于以产品为导向之前我会停在这里。
因此让DB处理FK约束的一些优点是:
答案 2 :(得分:0)
在数据库中创建FK约束的优缺点是什么? 本身而不是在应用程序级别管理它们?
使用db-enforced FK的一些优点:
从代码中分离出schmea。
缩小应用程序代码
程序员没有机会搞乱FK规则。
强制与db集成的其他应用程序遵循fk规则。
使用db强制FK的一些缺点。
如果您有特殊情况,不容易破解
如果数据无效,则可能会引发错误。应编写应用程序以优雅地处理错误,例如那些错误(特别是批处理错误)。
必须仔细定义和编码具有参照完整性规则的FK定义。您不希望在线级联删除1000000行。
它们会导致隐式检查,即使您不希望发生检查,因为您知道父行必须存在。这可能对性能产生微不足道的影响。在批量加载和OLAP / Data Warehouse系统中加载大量数据时,性能是一个问题。使用特殊加载工具,并且在加载期间通常禁用诸如数据库强制FK之类的约束。
从设计的角度来看,它们是否应该一起使用或 会导致冲突吗?
你可以将它们放在一起是有原因的。正如我之前提到的,您可能在数据中有特殊情况,无法为其定义FK。此外,在某些情况下,例如FK之间无法处理的表之间的多对多自引用关系(至少对于某些数据库引擎)。