是什么理由让你彻底抛弃数据库的外键?

2016-11-22 14:28:29 +08:00
 ljk

初涉后台开发未深,诚惶诚恐看 <SQL 反模式>,学习最佳实践。

发现现在这个项目应用了不少反模式,其中最让我困惑的是,完全不使用外键,涉及到外键的逻辑全部在应用代码里实现。

询问项目负责人,告知不使用数据库外键主要有两原因:

  1. 多台服务器不停机升级时,有可能数据库新加入的外键限制导致新程序没办法在旧数据库上跑
  2. 运维人员对数据库外键深恶痛绝(举例说唯品会就是这样做的)

听起来只要是分布式的服务器热升级(第一点原因)、或者团队里有运维人员,就应该抛弃数据库外键了。

业界都是这样做的吗?书上说的当真脱离了实际?

谢不吝赐教。

25668 次点击
所在节点    程序员
117 条回复
bomb77
2016-11-22 20:44:03 +08:00
233 ,原来大家都不用外键
echo111222
2016-11-22 20:47:08 +08:00
。。。。我记得我今年五月的时候,老师给我看看论文。。强行给我的数据库表加外键
xiaoxiaoming
2016-11-22 20:52:15 +08:00
做的都是互联网相关的业务.
从来没有用外键,都是靠业务逻辑区约束.
abcbuzhiming
2016-11-22 21:39:06 +08:00
首先要理解当年数据库为什么要设计这些,外键说白了就是为了维护数据强一致性的。当年的数据库在金融领域应用最多最早,所以强一致性要求很高。而现在绝大部分公司的业务,哪需要这么高的强一致性啊
abcbuzhiming
2016-11-22 21:41:54 +08:00
@jianghu52 你的项目用了 PHP 就说明你们的项目试图快速成型而不是打算长期维护的严谨系统,这种系统费精力去用外键是给自己找不愉快,浪费在开发上的时间比你不用外键而需要填坑的时间还要长。不用外键本质是因为现在绝大部分业务压根就不需要那么严谨的一致性了。这玩意是有代价的
icegreen
2016-11-22 21:45:18 +08:00
从来不用, 逻辑全部在代码中体现, 便于维护.
你的问题是为什么抛弃了外键; 不妨从另一个角度想想,为什么用外键. 把约束从代码转移到数据库, 有什么好处.
odirus
2016-11-22 21:49:18 +08:00
如果没有专业的 DBA ,还是少用
aldenchang
2016-11-22 22:09:20 +08:00
对于业务规则不够完善,经常需要工程师手动调整数据的库来说,外键简直是灾难。
jjx
2016-11-22 22:25:44 +08:00
看了这个讨论让人瞠目结舌, 虽说互联网应用对数据一致性要求不高, 但看到如此漠视, 所以这可能才是企业软件招不到合适的人的原因了
eyp82
2016-11-22 22:29:30 +08:00
数据库其实也从来没有要求大家用外键, 用外键只是为了满足某个范式的要求而已, 实际上范式根据严格程度不同有多重, 你甚至连第一范式都可以不满足(比如时下流行的 KV 数据库). 这并不是说数据库理论脱离实际.
所有的设计都是根据实际情况做各方面的妥协的, 比如企业应用(金融电信制造等等), 业务逻辑复杂但是并发量**相对**不高, 以前一般倾向于 scale-up, 不会做分库分表, 这样通过外键, trigger 等确保逻辑一致性是很合适的做法, 反之通过业务逻辑重复造轮子就不科学了.
互联网应用更多的是高并发, 单个业务逻辑本身一般并不复杂, 这样在业务逻辑内重复实现一个约束相对简单, 而由于分布式的要求, 外键是一个严重的阻碍, 所以不适用外键也在情理之中.

另外不同意楼上有人说的数据库的外键消耗更多系统资源的说法, 实际上数据库的外键经过这么多年的优化, 绝大多数情况下比业务代码里对关系数据库半懂不懂的人写的约束更高效. 你自己写的约束其实只是让你后面自己折腾起来更灵活而已.
icegreen
2016-11-22 22:56:46 +08:00
没有外键也还有事务, 放弃了外键 不等于 放弃了一致性.
不要歪题
iyaozhen
2016-11-22 23:14:21 +08:00
关键是不方便维护,其它都是次要的。后面接手的人容易搞出事故。不要说外键了,字段不能为 null 的限制都能出问题。存储过程什么的也一样,好多时候不知道别人设置了这些,容易踩坑。

不过更多的是业务不需要,没需求、没收益。使用上主要矛盾集中在索引优化、主从一致等,哪有精力倒腾外键。
IwfWcf
2016-11-22 23:16:00 +08:00
最主要的原因就是为了可扩展性吧,未来可能需要分表
colatin
2016-11-22 23:31:25 +08:00
关键楼上都是搞分布式大系统的
yeqiu
2016-11-22 23:45:23 +08:00
@anubiskong
完全同意你的说法,关系就是逻辑,逻辑放在程序里封装成变化,天经地义。

这里有一个大写的但是

建立外键和代码实现外键哪个是确保数据一致性的最低成本的方法?
我想这个问题的结果无疑是建立外键。

那么有没有一种既能使用外键的低成本,又能很好的封装变化的方式呢?
当然有, entity framework 的 code first 就是我知道一种方式,按理说所有的 orm 框架应该都能干这事
skywatcher
2016-11-22 23:48:22 +08:00
我们 DBA 团队的也强烈建议不要外键,数据库同步、迁移、分表、分库时各种约束很麻烦。之前一次想同步一个表的数据到 beta 环境,各种外键约束,最后基本整个库都快被同步下来了,我特么只要一个表而已😠(别问为啥不直接 dump ,线上数据库规定不允许 dump 影响业务)
guyskk
2016-11-23 00:02:22 +08:00
@ljk 软删除,一定时间后彻底删除。企业需要应对比如盗号,用户误删数据,管理员误操作,以及司法取证这些问题。
exoticknight
2016-11-23 00:04:06 +08:00
请教一下不用外键如何用业务逻辑区约束?
wind3110991
2016-11-23 00:13:39 +08:00
外键这个东西和触发器是一样的道理,平时工作上省事了,一旦出了问题,定位半天找不到原因;
举个最简单的例子:
假设有 学生表 Student 和 班级表 Class
学生表中关联了一个外键,字段是班级的 id ,
现在系统里有个学生 A 读了四年大学,所在班级为 B ,准备读研,读研就要换到班级 C 中,这个关联的班级 id 就要更新对吧;
但是这个时候假设学校教务系统不保留毕业班级的信息,会把毕业班级信息清除或者删除掉。这个时候就删掉了这个学生原来的班级 B (把班级表里 B 班级整条记录都删除了)。
A 学生到了研究生注册那天,去到报名处修改班级信息。这时候修改这个自己的班级时就会发现 DB 外键关联报错,而且不是代码逻辑的错误。

讲了半天。。就是让你,多写两行代码关联逻辑,少操份定位时想死的心。。
wind3110991
2016-11-23 00:15:00 +08:00
@exoticknight 新建并维护一个 map 表 C ,把 A 和 B 的关联记录到 C 中

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

https://tanronggui.xyz/t/322370

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

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

© 2021 V2EX