数据库是否应该使用外键约束?

本文探讨了数据库中外键约束的使用,指出其在确保数据完整性和一致性方面的优势,但同时带来了性能问题、死锁风险、分库分表难度以及开发测试效率的下降。大公司倾向于避免使用外键,以适应快速变化的业务需求。然而,在高可靠性场景下,如政务、银行等,外键约束仍然是必要的。建议根据业务复杂度在测试和生产环境中灵活运用。
摘要由CSDN通过智能技术生成

一、前言

对于【是否使用外键约束】这个话题已经是老生常谈的了。在学校中,老师交给我们的大多是需要我们建立外键约束,但进入了实际工作很多时候并不会使用外键,而是通过代码逻辑来控制。包括在阿里的JAVA规范中也明确规定:【强制】不得使用外键与级联,一切外键概念必须在应用层解决

为什么要做这样的规定呢?到底该不该使用外键约束呢?我们可以举一个例子来说明


二、举例说明

现在我们在数据库中建立了两张表:【product和project】,【project】的porduct字段,关联Product,他们之间存在下图这样的一条外键记录:
在这里插入图片描述


当我们对【project】表增加一条project_id为 1 的记录的时候,由于【product】表不存在相应的记录会导致报错:
在这里插入图片描述


可以看出,这个约束的存在,会保证表间数据的关系的完整性。更不容易出现脏数据。这是外键约束非常明显的优点!

总结一下,外键约束具有如下的优点:

  1. 保证数据的完整性和一致性
  2. 级联操作方便
  3. 将数据完整性判断托付给了数据库完成,减少了程序的代码量

但也存在着不可忽略的缺点:

性能问题

我们刚建立了两张表【project】和【product】,【project】表通过project_id字段与【product】表做了外键约束。

这个时候,当我们每次往【project】表插入数据的时候,它会先去【product】中查询是否有对应的关联数据,如果通过程序来控制可以不进行这次查询。但设立了外键约束,就一定会去进行该查询。这实际是冗余的。当关联的字段少的时候可能没啥影响,但一但关联字段多了后,这种影响就尤其明显!


死锁

外键导致查询需要依赖其他数据表,这意味着 InnoDB 需要在父级表(或相关表)中检验相应的值。这也会锁定父级表的数据行,以保证在事务完成前该行不会被删除。这会导致意外的锁等待,甚至是死锁,这类问题很难被定位。


分库分表困难

加了约束的数据库在需要分库分表的情况下,会特别困难


开发/测试效率的降低

在我们日常的测试过程中,经常会遇到发现了一个BUG想复现或者方便测试的情况,会直接改数据库表的数据来达到方便测试的效果。

虽然这及不规范,但实际情况就是能够提升我们很多效率。这是毋庸置疑的!可是,这样的操作也会带来一些问题,比如因为数据导致的BUG,但实际并不是程序的BUG,或者发现不了一些潜在的BUG。


三、总结

目前很多互联网公司,特别是大厂对于外键的态度都是要求禁用。这其实不单单因为性能问题,主要也因为互联网的业务变化快,会间接导致表结构容易发生变动,很可能会因为外键约束的存在导致导意想不到的问题和开发效率的降低。因此,在非必要的情况、不需要高可靠性的业务场景下,不建议使用外键约束,这样更能够拥抱变化。
但我们并不能一杆子打死,因为有的业务场景反而使用外键约束更好,比如政务、银行、军工等需要数据高可靠的情况下。所以我的建议是:如果是业务相对复杂的话,可以在测试环境使用外键约束,但上了生产环境需要去掉。如果业务相对简单,那完全可以删除外键约束。但对于银行、军工行业这些不允许数据出错,需要高可靠性的场景下,还是建议建立外键约束。

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曲鸟

不要打赏,没必要!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值