为何大多数互联网公司不用外键约束

是否使用外键约束

【强制】不得使用外键与级联,一切外键概念必须在应用层解决.-《阿里Java规范》html

首先外键(Foreign Key)是什么东西

使用方案

假设有一个score表 id是自增id,score是分数,student_id是学号。sql

另外一个student表,id是自增id,name是名字,student_id是学号。数据库

那么设计这个的时候就但愿有一个关联关系,让score的student_id指向student表的student_id,存在一个学生对应多个成绩的关系。因此我可使用如下SQL语句服务器

ALTER TABLE score
ADD CONSTRAINT FOREIGN KEY (student_id)
REFERENCES student(student_id);

建立一个外键索引完成这个规则并发

完成后的表关系以下框架

外键原理

被指向的字段,具备惟一性高并发

能够保证成绩字段的一致性,即每一次插入一个score数据,首先要检测是否student表存在这个id,保证一致性性能

若是在外键类型上使用CASCADE,则会保证在作更新和删除sutudent表的student_id时,触发一次级联操做,会同步更新score表的student_id或者删除student_id.设计

外键类型RESTRICT 也一样会作一次检测,但不会作级联操做,而是直接拒绝操做。
3d

场景思考

知道外键是什么后,咱们来思考一个场景:

如今有一个电商系统,用户有一个帐户id,商品有一个商品id,这两个字段和订单绑定,此时订单id和帐户表ID构成一个外键关系,同时和商品表id也构成一个外键关系,那么我每次生成一笔订单,就须要向另外两张表查询检测一次数据,那么就存在几个问题:

  • 增删改触发这个查询操做的性能消耗,服务器系统是否容许
  • 在其余表查询会上须要对其余表作一个内部锁,是否存在高并发死锁状况
  • 数据一致性所有交给数据库服务器,数据库服务器是否可以承受

这些问题在互联网公司会显得格外严重,由于访问流量大的时候以上问题基本上是彻底没法获得MySQL系统自己解决的

同时在作分库分表设计的时候,外键约束就会显得格外离谱。

同时MySQL系统的外键设计是背离部分SQL标准的

引用自博客园Eden: (https://www.cnblogs.com/discuss/articles/1862244.html)

对SQL标准的背离:若是ON UPDATE CASCADE或ON UPDATE SET NULL递归更新相同的表,以前在级联过程当中该表一被更新过,它就象RESTRICT同样动做。这意味着你不能使用自引用ON UPDATE CASCADE或者ON UPDATE SET NULL操做。这将阻止级联更新致使的无限循环。另外一方面,一个自引用的ON DELETE SET NULL是有可能的,就像一个自引用ON DELETE CASCADE同样。级联操做不能够被嵌套超过15层深。

对SQL标准的背离: 相似通常的MySQL,在一个插入,删除或更新许多行的SQL语句内,InnoDB逐行检查UNIQUE和FOREIGN KEY约束。按照SQL的标准,默认的行为应被延迟检查,即约束仅在整个SQL语句被处理以后才被检查。直到InnoDB实现延迟的约束检查以前,一些事情是不可能的,好比删除一个经过外键参考到自身的记录。

处理

由于以上问题,咱们一般在建模时隐性设计外键约束,实际实现采用业务逻辑模拟外键的方式处理,这样能够解决把一致性所有放在DBA上的性能问题,同时咱们能够采用容许脏数据存在,而后定时数据清理的方案去保证数据处理的分时性能,避免高峰处理。

这样的好处:

  • 解决性能问题
  • 增长了可扩展性,框架迁移不用在数据库系统内部实现逻辑约束
  • 分库分表的时候方便
  • 不会在DB层面形成死锁

反推:是否可使用外键约束

我以为在部分业务场景下是能够考虑使用的,回到最开始的例子,教务系统的成绩模块重要的点再也不是性能问题,而是高可靠,由于对学校来讲,系统存在如下特色:

  • 数据量较少,一个学校学生最多不超过10万人,一般在5000-50000这个区间内,对DB来讲这是一个很小的数据量
  • 数据不允许出错,由于成绩和学生的人身利益直接挂钩
  • 可以进行数据修改操做的用户极少,只有教务处录入成绩的老师。
  • 若是放在业务部分,若是出现student表student_id在第一次被删除后,未清理score表数据,这个student_id短期内被再次使用,而没有作数据清理,就容易出现成绩复用错误,诸如此类

因此 不得使用外键与级联,一切外键概念必须在应用层解决。 大部分状况下正确,但一样我认为须要分业务场景解决,并不能一竿子打死。

相关文章
相关标签/搜索