为什么不推荐使用外键与级联?
为什么不推荐使用外键与级联?
-
不是不能用外键,而是在高并发、分布式、读写分离架构下,数据库层面的强约束会成为系统扩展性的“隐形枷锁”。很多互联网公司选择在应用层维护关系,而不是依赖数据库外键和级联。
-
外键(Foreign Key)本质是数据库级别的引用完整性约束。比如:
- child 表的 user_id 必须存在于 parent 表
- 删除 parent 时,child 要么禁止删除,要么级联删除
- 数据库会在每次 INSERT / UPDATE / DELETE 时做一致性检查。
为什么不推荐使用外键与级联?
- 影响性能
外键会让数据库在修改数据时做额外检查。高并发写场景下:
- 每次写都要查父表
- 可能加锁
- 级联删除会触发大量额外操作
当数据量上亿时,这不是“小开销”。
- 降低扩展性(分库分表 nightmare)
一旦做分库分表,问题就来了。假设 user 表和 order 表被拆到不同数据库实例。数据库层面已经无法做跨库外键。
于是:
- 要么放弃外键
- 要么永远不能拆库
而大规模系统最终几乎都会拆库。
外键 = 强耦合 = 垂直扩展障碍。
- 级联删除风险极高
假设:
- 删除一个 user
- 触发删除 10 万条 order
- 再触发删除 order_item
- 再触发日志表删除
结果可能是:
- 误删灾难
- 长事务
- 大面积锁表
- 业务逻辑不应该埋在数据库
现代架构更推崇:
- 数据库负责存储
- 业务逻辑在应用层
级联删除本质是业务规则。
而规则往往会变化:
今天允许级联
明天改成逻辑删除
后天改成归档
数据库约束一旦上线,修改成本很高。
结论
- 使用外键和级联的问题:
- 影响性能
- 影响扩展性(分库分表)
- 级联删除风险极高
- 业务逻辑不应该埋在数据库
