【问题标题】:Database FK Constraints vs Programmatic FK Constraints数据库 FK 约束与程序化 FK 约束
【发布时间】:2018-06-28 16:20:53
【问题描述】:

虽然我的目标是 MySQL/PHP,但出于我的问题,我想将其普遍应用于与现代编程语言结合使用的任何关系数据库。另一个假设是该语言正在利用一个现代框架,该框架在某种程度上可以隐式处理外键约束,或者有一种方法可以显式处理。

我的问题:

  • 与在应用程序级别管理它们相比,在数据库本身创建 FK 约束有哪些优缺点?

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

  • 如果它们不应该一起使用,关于使用哪种方法被认为是“最佳实践”?

注意:这是一道设计理论题。由于可用于满足实现的技术种类繁多,我对实现的任何细节并不真正感兴趣。

【问题讨论】:

  • Myslq 比 PHP 快得多,而且它专为数据完整性而设计,为什么要在 php 中这样做?
  • @Mihai 我并不是要建议我以某种方式想要它。这就是我问这个问题的原因:)
  • 在应用程序中管理 FK 约束没有“专业”。只是为以后的灾难打开了大门。这就是 DB 的设计形式

标签: database database-design


【解决方案1】:

与在应用程序级别管理它们相比,在数据库本身创建 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

【讨论】:

    【解决方案2】:

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

    恕我直言,最佳做法是将工具用于创建它们的目的。 DB 负责 FK 的引用完整性,应用程序不需要关注 DB 的内部功能。但是,如果引用完整性是您主要关心的问题,并且您例如将 MySQL 与不支持 FK constraints 的 MyISAM 引擎一起使用,那么您必须手动检查应用程序(或者可能使用我不熟悉的 DB 触发器) .请记住,当您执行各种签入应用程序时,您仍然必须访问数据库,因此如果数据库可以处理引用完整性检查,您使用的资源比实际需要的资源要多。 (当然,简单的解决方案是使用 InnoDB engine 开始,但我会在此答案过于面向产品之前停在这里)。

    所以让数据库处理 FK 约束的一些优点是:

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

    【讨论】:

      【解决方案3】:

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

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

      1. schmea 与代码的分离。

      2. 使应用程序代码更小

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

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

      使用 db-enforced FK 的一些缺点。

      1. 有特殊情况不容易破解

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-16
        • 2011-12-29
        相关资源
        最近更新 更多