Database FK Constraints vs Programmatic FK Constraints

前端 未结 3 561
既然无缘
既然无缘 2021-01-24 19:00

Although I am targeting MySQL/PHP, for the sake of my questions, I\'d like to just apply this generally to any relational database that is being used in conjunction with a moder

3条回答
  •  北荒
    北荒 (楼主)
    2021-01-24 19:37

    What are the pros and cons of creating FK constraints in the database itself as opposed to managing them at the application level?

    In a concurrent environment, it is surprisingly difficult to implement referential integrity in the application code, such that it is both correct and with good performance.

    Unless you very carefully use locking, you are open to race conditions, such as:

    • Imagine there is currently one row in the parent table and no corresponding rows in the child.
    • Transaction T1 inserts a row in the child table, but does not yet commit. It can do that since there is a corresponding row in the parent table.
    • Transaction T2 deletes the parent row. It can do that since there are no child rows from its perspective (T1 hasn't committed yet).
    • T1 and T2 commit.
    • At this point, you have a child row without parent (i.e. broken referential integrity).

    To remedy that, you can lock the parent row from both transactions, but that's likely to be less performant compared to the highly optimized FK implemented in the DBMS itself.

    On top of that, all your clients have to adhere to the same "locking protocol" (one misbehaving client is enough to currupt the data). And the complexity rapidly raises if you have several levels of nested FKs or diamond-shaped FKs. Even if you implement referential integrity in triggers, you are only solving the "one misbehaving client" problem, but the rest remains.

    Another nice thing about database-level FKs is that they usually support referential actions such as ON DELETE CASCADE. And all that is simple and self-documenting, unlike referential integrity burried inside application code.

    From a design standpoint, should they ever both be used together or would that cause conflict?

    You should always use database-level FKs. You could also use application level "pre-checks" if that benefits your user experience (i.e. you don't want to wait until the actual INSERT/UPDATE/DELETE to warn the user), but you should always code as if the INSERT/UPDATE/DELETE can fail even if your application-level check has passed.

    If they should not be used together, what is considered the "best practice" in regards to which approach to use?

    As I stated, always use database-level FKs. Optionally, you may also use application-level FKs "on top" of them.


    See also: Sql - Indirect Foreign Key

提交回复
热议问题