关于外键,为什么国内基本都不推荐使用,国外基本都推荐使用?

2021-09-04 17:38:25 +08:00
 JasonLaw

国内的一些讨论:

国外的一些讨论:

16445 次点击
所在节点    程序员
128 条回复
JasonLaw
2021-09-05 07:00:49 +08:00
@agagega #55 同意你所说的“ 互联网公司的业务不太追求完整的数据一致性”
JasonLaw
2021-09-05 07:02:55 +08:00
@passerbytiny #57 什么叫数据库编程?什么叫应用编程?
Rocketer
2021-09-05 07:42:38 +08:00
@JasonLaw 因为踩的坑多了,就知道外键对改需求来说是个累赘。你要非让我具体说个案例,你一定觉得这也没啥,但架不住多啊!烦啊!

关键是为啥一定要用外键?奥卡姆剃刀原则在设计系统时一样有效——如无必要,勿增实体。不能因为它在某些角度看起来有好处就无脑用。

一致性对某些场景很重要,但多数互联网企业并不在意这个。据说连支付宝的交易记录都允许出错,每天都会因为对不上账而赔几万块钱。但你要他保证一致性,那成本怕是远远远远远超每天几万块。
JasonLaw
2021-09-05 08:18:36 +08:00
@agagega #55
@JasonLaw #61
@Rocketer #63

这里纠正一下,外键跟一致性( Consistency )没有太大的关系,更正确的说法是:外键能够保证 referential integrity 。Consistency 不是数据库本身的一个特性,它是应用怎么使用数据库的一个特性。
zjsxwc
2021-09-05 08:25:48 +08:00
illuz
2021-09-05 09:07:32 +08:00
为什么拿 stack overflow 这样的学术性偏强的问答帖子和 v 站水帖比,你可以去搜搜 reddit 帖子或去老外的技术群组讨论,确认一下老外确实大部分都会用 FK 再来提问。
或者直接去捞一些 GitHub 项目,统计一下 FK 的使用情况。
反正我随便搜了一下,发现老外们也有不少不用 FK 的,类似你这样的帖子讨论也不少。
JasonLaw
2021-09-05 10:23:00 +08:00
@illuz #66 能够提供一下你所查阅的资料吗?我看到的绝大多数都是倾向使用外键的。

Google 搜索“foreign key database or application reddit”得到的一些结果:

* Are foreign keys really necessary in a database design? : programming - https://www.reddit.com/r/programming/comments/6xidz/are_foreign_keys_really_necessary_in_a_database/
* What Would Happen If Foreign Keys Not Used? : Database - https://www.reddit.com/r/Database/comments/ef38aq/what_would_happen_if_foreign_keys_not_used/
* Don't Most Databases Have Foreign Key Constraints? : SQLServer - https://www.reddit.com/r/SQLServer/comments/6wz2hu/dont_most_databases_have_foreign_key_constraints/dmd7dj1/
* ...
fengpan567
2021-09-05 10:28:28 +08:00
其实我也不喜欢用,为什么要让数据库去约束业务
zjsxwc
2021-09-05 10:37:25 +08:00
@gBurnX #37
并没觉得有问题,而且业务上负责人不是岗位。
我觉得没必要为了使用外键而修改业务。
JasonLaw
2021-09-05 10:39:38 +08:00
@fengpan567 #68 请问你有使用 primary key, unique 等数据库提供的约束吗?有使用事务吗?
msg7086
2021-09-05 11:03:58 +08:00
所以你说的是数据库物理外键还是说框架里的逻辑外键?

我觉得逻辑外键要有,但是物理外键还是算了吧。
物理外键删数据的时候连 hook 都不会走,天知道会漏跑什么东西。
JasonLaw
2021-09-05 11:10:46 +08:00
@msg7086 #71

更加准确的说,是数据库的 foreign key constraint 。

“物理外键删数据的时候连 hook 都不会走,天知道会漏跑什么东西”是什么意思?可以具体描述一下吗?
msg7086
2021-09-05 11:24:19 +08:00
@JasonLaw ORM 在执行数据写入的时候是可以往上挂钩子做额外处理的。

举个简单的例子。你有两个表,一个用户表,一个帖子表,帖子外键连到用户。

现在你把一个用户删了,那么这个用户对应的帖子就需要做适当的处理。
比如你可以在用户的删除钩子上,把他发的所有帖子的用户 ID 都改成一个特殊用户的 ID 。
这样那些帖子就不会被删除了。
当然,这个钩子里还可以做其他的操作,比如更新用户的发帖数,更新页面缓存,等等。

而用数据库外键的话,你一做级联删除,这些帖子就消失不见了,你也没法在对象上加钩子来处理这些事件。
换句话说,数据库背着程序做了一些修改,而程序没有感知。
这个行为我觉得是很可怕的。

所以我宁愿让 ORM 来负责一致性。我想级联删除就级联删除,我想用钩子做其他处理,就绑钩子。
JasonLaw
2021-09-05 11:30:04 +08:00
@msg7086 #73 ON DELETE CASCADE 是可选的。
msg7086
2021-09-05 12:20:07 +08:00
@JasonLaw 但是做外键不就是为了强一致性么。
JasonLaw
2021-09-05 12:28:16 +08:00
@msg7086 #75 保证 referential integrity
illuz
2021-09-05 12:28:39 +08:00
@JasonLaw 你这几个帖子里面就有一些非外键派的吧,没有绝大部分哈
illuz
2021-09-05 12:35:42 +08:00
我只是对帖上文的 stack overflow 和 v2 对比方式表达一下看法,感觉这个讨论前提不够有力
skiy
2021-09-05 12:51:42 +08:00
@gBurnX 关于准确这个方面, 这个说得没错. 但你 `mysqldump` 出来一个库后, 然后直接 `source` 进去却报错. 这个你受得了? 试想几百个表, 然后还要一个一个地对比着先后顺序吗? 如果没有文档说明, 没人会想到会是这种问题. 当初我就是吃过这方面的亏. (我不是专业的 DBA)
azuis
2021-09-05 12:53:50 +08:00
@skiy 导入导出的时候问题不大吧。可以暂时禁用外键检查,导入完成后再启用即可。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/799876

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX