• 为什么我不建议你使用外键


    MySQL 外键(Foreign Key)是用于建立表之间关系的,它定义了一个表中的一列或一组列,这些列的值必须在另一个表的主键列中存在。

    MySQL 外键最大的作用就是有助于维护数据的一致性和完整性

    • 一致性:如果一个订单表引用了一个客户表的外键,外键可以确保订单的客户 ID 存在于客户表中,从而保持数据的一致性。

    • 完整性:外键可以防止在引用表中删除正在被其他表引用的记录,从而维护数据的完整性。

    但是,其实在很多大型互联网公司中,很少用外键的,甚至阿里巴巴 Java 开发手册中明确规定了:

    【强制】不得使用外键与级联,一切外键概念必须在应用层解决

    说明: 以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群; 级联更新是强阻塞,存在数据库更新风暴的风险; 外键影响数据库的插入速度。

    那么,使用外键会带来哪些问题呢?

    先举个例子,我们有两张表:Orders(订单)和 OrderItems(订单项)。这两个表之间通过外键建立关系,订单项表中的外键引用订单表的订单号。

    CREATE TABLE Orders (
        OrderID INT PRIMARY KEY,
        CustomerID INT,
        OrderDate DATE,
        -- 其他订单信息
    );
    
    CREATE TABLE OrderItems (
        ItemID INT PRIMARY KEY,
        OrderID INT,
        ProductID INT,
        Quantity INT,
        -- 其他订单项信息
        FOREIGN KEY (OrderID) REFERENCES Orders(OrderID)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    性能问题

    首先就是性能问题,因为外键会增加数据库的维护负担,因为每次插入、更新或删除数据时,数据库都需要检查外键约束的完整性。

    这两张表中共有两个索引,一个是 Orders 表的主键索引,一个是 OrdersItems 表的外键索引,这就使得每次插入、更新或删除订单或订单项时,数据库需都要维护这两个索引,这可能会导致性能开销。

    其次,在插入新的订单项之前,数据库需要执行数据一致性检查以确保引用的订单号在 Orders 表中存在。这额外的检查可能增加插入订单项的执行时间。

    锁竞争问题

    还有就是比较容易忽略的锁竞争问题。当多个事务同时尝试插入或更新订单项时,它们就需要去检查订单表,就需要获得额外的锁,以确保一致性。这可能导致事务之间的锁竞争,降低并发性能。

    一旦有了锁竞争,就可能带来更加严重的死锁问题,所以都是需要尽量避免的。

    Merge 无法适应分库分表

    当数据量大的时候,我们就要考虑分库分表了,但是在分库分表环境中,相关数据可能分布在不同的数据库中,外键通常难以跨越不同数据库来建立关系。更重要的是,分库分表环境中,数据的一致性可能更难维护。跨库事务搞不定。

    以上,就是一些比较重要的原因吧。其实最主要的还是外键约束会带来一些额外的开销及锁竞争。而在很多大型互联网公司中,都是会尽量避免的。

    就像大厂会使用 RC 来替代 RR 一样,会尽可能的降低锁的发生,一方面提升性能,一方面避免死锁。

  • 相关阅读:
    JVM调优实战
    [附源码]计算机毕业设计JAVA小区宠物管理系统
    linux环境下查询主板、CPU、内存等硬件信息
    创建Django项目_first_Django(下)
    Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?
    Spring 手把手入门实例
    python学习笔记——列表
    【芯片前端】根据数据有效选择输出的握手型FIFO结构探究
    SpringMvc中RequestMapping注解
    循环队列的实现及应用——桶排序bucket_sort、基数排序radix_sort
  • 原文地址:https://blog.csdn.net/agonie201218/article/details/134260125