简单回答:
- 参照完整性是必须的
- 缓存是一个有资格的必须品
- 触发器是一种很好的东西
更长的回答:
自1993年以来,我一直在关系型数据库上开发应用程序(Dec RDB,之前是在平面文件系统上),由于触发器可以“删除您不想删除的内容”,因此许多开发人员从未喜欢过触发器。参照完整性也经常被开发人员所反对,因为在第三正规形式下具有适当的参照完整性的数据库很难在几分钟内组合在一起。
尽管许多系统可以在没有触发器的情况下运行,但我认为没有参照完整性,任何应用程序数据库都无法舒适地生存。看看这个问题的标签,这个网站背后的数据库将拥有一个标签表(可能称为“Tag”)和一个问题表(可能称为“Question”)。 “Question”将具有对Tag表主键的外键,但由于问题可以有多个标签,标签也可以有多个问题,因此我猜测关系如下:
Question
(TagId) 1 | Database triggers / referential integrity and in-memory caching
|
-----
| | |
QuestionTag
(QuestionId) 1 | 1 ... 1 | 2 ... 1 | 3 ...
(TagId)
| | |
-----
|
Tag 1 | database ... 2 | referential-integrity ... 3 | triggers ...
(TagId)
这种引用完整性是任何可靠应用程序的基础,不容许妥协。你可以看到它如何增加应用程序设计的可信度和对其长期性的信心。
SO上的缓存可能已经开启了标签等功能(虽然不能保证),所以假设标签已经被缓存在内存中,并且您拥有足够的声望来允许向SO添加标签。您添加了标签,它可能会立即持久化到数据库中,但缓存是否会被更新呢?
这是一个权衡。如果不知道您的新标签,该站点能否生存?如果可以,那么需要多久?从用户添加到数据库中,再到其他用户可用并被使用,标签的生命周期是什么?缓存将根据开发团队制定的规则进行重建,而这个规则本质上是一种权衡,以便任何新标签都可以在不减慢应用程序速度的情况下快速可用。
触发器可以强制执行引用完整性,例如您添加的标签是“垃圾”,但管理员看到它时,已经有三个问题被标记为“垃圾”。管理员随后决定删除“垃圾”标签,但标记为它的问题怎么办?如果在“标签”表上有一个触发器,在删除时触发,它可以绕过“问题”表并删除所有对“垃圾”的引用。有很多这种方法的替代方案,其中许多是编程解决方法,但是否有更简洁的解决方案呢?
在过去的20年里,我参与了许多网站的开发,好的网站都使用引用完整性和越来越多的缓存。更改数据的触发器(本质上只是事件驱动的存储过程)并不受欢迎,并且越来越被误解,但仍然有其作用。
缓存和引用完整性不能被视为二选一,开发团队必须设计应用程序,以便两者都可以被纳入其中。