数据库约束发生了什么?


46

当我查看RDBMS的数据库模型时,通常会惊讶地发现几乎没有约束(除了PK / FK)。例如,百分比通常存储在类型的列中int(虽然tinyint会更合适),并且没有CHECK约束将值限制为0..100范围。同样在SE.SE上,建议检查约束的答案通常会收到注释,表明数据库是约束的错误位置。

当我询问不实施约束的决定时,团队成员会回答:

  • 他们甚至都不知道自己喜欢的数据库中是否存在这样的功能。对于仅使用ORM的程序员而言,这是可以理解的,但是对于声称拥有给定RDBMS 5年以上经验的DBA而言,这是可以理解的。

  • 或者它们在应用程序级别强制执行此类约束,并且在数据库中复制这些规则不是一个好主意,这违反了SSOT。

最近,我看到越来越多的项目甚至不使用外键。同样,我在SE.SE上看到了一些评论,这些评论表明用户不太在意引用完整性,让应用程序来处理它。

当询问团队有关不使用FK的选择时,他们说:

  • 例如,当必须删除其他表中引用的元素时,它就是PITA。

  • NoSQL坚如磐石,那里没有外键。因此,我们在RDBMS中不需要它们。

  • 就性能而言,这并不是什么大问题(上下文通常是在小型数据集上运行的小型Intranet Web应用程序,因此,实际上,即使索引也没有太大关系;没有人会介意给定查询的性能是否超过1.5 s到20毫秒)。

当我查看应用程序本身时,我系统地注意到了两种模式:

  • 该应用程序会正确清理数据并在将其发送到数据库之前对其进行检查。例如,无法102通过应用程序将值存储为百分比。

  • 该应用程序假定来自数据库的所有数据都是完全有效的。就是说,如果102以百分比来表示,某处某处将崩溃,或者仅将其按原样显示给用户,从而导致奇怪的情况。

  • 尽管超过99%的查询是由单个应用程序完成的,但随着时间的流逝,脚本开始出现-要么在需要时手动运行脚本,要么执行cron作业。还可以手动对数据库本身执行某些数据操作。脚本和手动SQL查询都具有引入无效值的高风险。

这是我的问题:

没有关系约束而最终甚至没有外键的关系数据库建模的原因是什么?


就其价值而言,这个问题和我收到的答案(尤其是与Thomas Kilian进行的有趣的讨论)使我写了一篇有关数据库约束的结论文章


8
我对您有帮助,但是您似乎已经知道为什么约束是一个好主意,因此在答案的形式上没什么可添加的。不过,我会指出,缺乏约束并不是一个新现象,数十年来,我在开发人员设计的数据库中就已经看到过这种情况,而他们对关系数据库没有很深入的了解。我认为这很少是故意设计的决定。
JacquesB,2016年

1
@JacquesB:您可能会发布一个答案,因为“我已经看了几十年”给出了一种截然不同的看法,即我对三四年前出现的一种现象有一个看法(假设我从事IT工作的时间不足十年,我对这种现象的看法可能是错误的)。因此,结论也将非常不同。
Arseni Mourzenko '16

1
我们与许多客户合作。虽然推出我们软件的新版本是轻而易举的事,但是更新所有数据库chema的所有内容都是一件痛苦的事情。这就是为什么我们在软件方面有最多的限制。哦,是的,一个百分比的tinyint通常不是一个好主意,因为百分比可以是分数。
Pieter B

1
投票重开此问题,因为到目前为止的答案表明事实并非如此,该问题已被错误地关闭为“主要基于意见”。
David Arno

3
我和你在一起110%
佩里亚塔·布雷塔

Answers:


28

区分数据库的不同用例很重要。

多个独立的应用程序和服务可能会直接访问传统的业务数据库,也许授权用户也可以直接访问。在数据库级别拥有经过深思熟虑的架构和约束至关重要,因此单个应用程序中的错误或疏漏不会破坏数据库。数据库对业务至关重要,这意味着不一致或损坏的数据可能会对业务造成灾难性的后果。当应用程序来来往往时,数据将永远存在。这些地方可能有专门的DBA,以确保数据库的一致性和运行状况。

但是,在某些系统中,数据库与单个应用程序紧密集成在一起。具有单个嵌入式数据库的独立应用程序或Web应用程序。只要单个应用程序可以独占访问数据库,就可以认为约束是多余的-只要该应用程序可以正常工作。这些系统通常由程序员开发,专注于应用程序代码,可能对关系模型没有深入的了解。如果应用程序使用ORM,则可以在ORM级别以应用程序程序员更熟悉的形式声明约束。在低端,我们有使用MySQL的PHP​​应用程序,而且很长一段时间以来,MySQL根本不支持基本约束,因此您必须依靠应用程序层来确保一致性。

当来自这些不同背景的开发人员见面时,您会遇到文化冲突。

在这种混合中,我们得到了新的分布式“云存储”数据库浪潮。在不失去性能优势的情况下保持分布式数据库的一致性非常困难,因此这些数据库通常避免在数据库级别进行一致性检查,并且基本上让程序员在应用程序级别进行处理。不同的应用程序具有不同的一致性要求,尽管Google搜索引擎将可用性优先于服务器之间的一致性,但我愿意打赌他们的工资系统在具有很多约束的关系数据库上运行。


5
+!1提到房间里的大象:一个应用程序仅使用一个DB且一个应用程序仅使用一个DB的错误假设
TulainsCórdova2016年

4
@TulainsCórdova,我认为这里房间里的大象是Google的工资系统。:)
Machado

5
@Machado这是个天才:“我愿意打赌他们的工资系统在具有很多约束的关系数据库上运行。”
图兰斯·科尔多瓦

2
由于应用程序代码不是ACID,因此具有适当约束的数据库也很方便。
马修·怀特

3
仅强调@MatthewWhited的评论,应用程序无法在不执行锁定和运行额外查询的情况下强制执行某些行间/表间约束。RDBMS可以以更低的成本实现此目的。
大卫·奥尔德里奇

15

如今,越来越多的系统在云上的分布式环境中运行,并采用“横向扩展”而不是“纵向扩展”的技术。如果您要处理面向在线互联网的应用程序(例如电子商务应用程序),那将更加重要。

话虽如此,所有应该扩展的应用程序都受CAP定理的约束,您必须在其中选择2:3:一致性,可用性和分区容限(网络容错)。

通过研究CAP定理,您会发现没有太多选择,而是选择失去“可用性”或“一致性”,因为您永远不可能真正100%地信任网络。

通常,几个应用程序可以在合理的时间范围内保持不一致,但不能让用户无法使用。例如,在Facebook或Twitter中,时间顺序稍微有些无序,总比根本无法访问时间线更好。

因此,由于关系数据库确实很擅长于一致性,但是却以可用性为代价,因此有几个应用程序选择放弃关系数据库约束。

个人说明:我也很老套,并且我一直在与一些真正的老式财务系统一起工作,在这些系统中,大多数时候数据一致性是一流的要求,并且我非常喜欢数据库约束。数据库约束是抵御年复一年的不良开发和来来往往的开发人员团队的最后一道防线。

“ Est方式重用”。让我们继续使用数据库“低级”一致性,其中一致性是一流的要求。但是有时候,放手毕竟不是大罪过。

-编辑:-

由于问题中的内容很小,因此还有另一个合理的理由来删除数据库中的约束IMO。如果您从头开始设计产品,并在其中设计系统以支持多数据库技术,那么您可能会满足于所支持数据库中最小公分母的要求,并最终放弃使用任何约束,而将所有控制逻辑留给你的申请。

尽管这是合法的,但对我来说也是一个灰色地带,因为今天我找不到任何不支持简单约束(如原始问题中提出的约束)的数据库引擎。


“如今,我只是找不到任何不支持简单约束(如原始问题中提出的约束)的数据库引擎。” MySQL是否支持CHECK约束?
文森特·萨瓦德

@VincentSavard,也许不是确切的CHECK MS SQL,但它确实有某种限制:dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html
Machado

@Machado-不过,这与特定的约束无关,它不仅可以识别查询何时包含了无法以适当类型表示的数据。这是对多年前MySQL只是默默地忽略了这些值的情况的明显改进。
佩里亚塔·布雷塔

1
附带说明一下,@ PeriataBreatta,当PostgreSQL完全可用且更高级时,我从未完全理解为什么MySQL是网站开发人员选择的“事实上的” OSS数据库。我不知道,也许安装起来更容易。
马查多

@machado-我不确定,但我知道在早期(90年代中期),我倾向于使用mysql而不是postgres(直到后来才重命名为postgresql),原因是对postgres的误解不支持SQL(它的早期版本不支持SQL-它有自己的查询语言称为“ postquel”-我也没有及时了解其开发情况,因此没有意识到他们大约在大约增加了SQL支持同时mysql可用)。如果这种误解很普遍,则mysql可能因此而领先。一旦取得成功,网络效应就会接管。
Periata Breatta

10

没有关系约束而最终甚至没有外键的关系数据库建模的原因是什么?

首先让我们弄清楚,我在这里只谈论RDBM,而不是谈论无SQL数据库。

我见过一些没有FK或PK的数据库,更不用说检查约束了,但说实话,它们只是少数。也许是因为我在一家大公司工作。

根据我多年的经验,我可以说一些原因可能是:

  • 对于初学者业余程序员而言,缺乏建模技能
  • 在没有与数据库世界真正接触的情况下广泛或几乎专有地使用ORM
  • 团队或小型项目中没有DBA或其他数据建模专家
  • 在开发的最初阶段,DBA或数据建模专家缺乏参与
  • 开发人员社区的一部分进行的故意设计决策认为,即使是强制某个列只能1,2 or 3作为值或“ age”列必须>= 0强制”的检查约束也是“在数据库中具有业务逻辑”。甚至默认子句在某些情况下也被视为不属于数据库的业务逻辑,正如您在此站点上最近出现的一些问题和解答中所看到的那样。如此考虑的开发人员显然将使用尽可能少的约束,并且会执行代码中的所有内容,甚至参照完整性和/或唯一性。我认为这是一个极端的立场。
  • 使用RDBM作为键值存储库,以模拟no-SQL行为,因为使用RDBMS表作为满足要求的简单程度足以隔离键值存储库。
  • 假设数据库将始终由“应用程序”写入,并且没有人需要进行海量数据加载或通过SQL客户端编辑或插入行(在许多情况下,可以更正应用程序插入的不良数据)。在最佳情况下,总是会有另一个应用程序(“应用程序”之外)向数据库发布DML指令:SQL客户端。
  • 没有意识到数据属于企业主,而不是应用程序。

话虽如此,我想指出RDBMS是已经在巨人的肩膀上构建的非常先进的软件,并且已经证明对于许多业务需求非常有效,从而解放了程序员的繁琐任务,使他们可以在一系列任务上强制执行引用完整性。二进制文件或文本文件。就像我经常说的那样:“我们不再生活在一个单应用一数据库的世界中”。至少,SQL客户端除了“应用程序”外还将发布DML。因此,数据库应在合理范围内保护自己免受人为或编程错误的侵害

在那些众所周知的需求中,RDBMS无法很好地扩展,因此一定要使用no-SQL技术。但是令人担忧的是,关系数据库的泛滥成灾,其中成千上万行代码(生成或键入的代码)专门用于执行RDBMS应该以更有效的方式为您实施的代码。


3

存在决定技术决策的外部约束。在极少数情况下,您需要定期使用数据库字段约束和(或)奢侈地使用它们。

  1. 企业拥有应用程序和数据库以及DBA的开发人员,但是大多数开发人员都无法在这种环境中工作。他们在代码中尽其所能。此外,数据库方面的某些人员不参与业务规则。他们主要是在那里保持运转。他们永远不会在数据库中施加约束。不得不处理遗留应用程序,集成,迁移,合并,收购数据库约束可能是最好的解决方案。
  2. 重载数据库可能会造成瓶颈,而通过将更多的计算机投入该问题很难解决。在某些情况下,db语言在不影响性能的情况下无法解决某些编程问题,因此您无法计划对所有内容都使用约束。Stackoverflow有一个数据库服务器,因为在一个问题上抛出2是一个挑战。
  3. 自动化测试-他们到了那里,但是许多数据库开发人员与IDE /测试框架一起迟到了。
  4. 部署-更多的数据库资料使其变得更加复杂。当由于存在违反约束的数据而不允许更新客户端数据库时会发生什么?除非您有解决此问题的方法,否则请结束游戏。在您的应用中,您可以决定让用户根据需要进行处理,或指示某些管理员批量进行处理。
  5. 只有app / api / service才能将数据写入数据库,所以为什么要打扰呢?在大多数情况下,这确实会占用时间,这就是为什么它不常见的原因。
  6. 如果一切顺利,处理数据库错误就足够困难而又没有数百个违反约束的问题了,大多数人都乐于建立连接并正确设置表名。

许多开发团队不想给数据库开发人员太多的控制权。如果您获得了不止一个,那您将很幸运,因此假期很有趣。没有多少要求对数据库域进行绝对控制,并且对每个查询,业务规则,性能,可用性,安全性以及将哪些数据存储到哪个RAID负责。这是允许您执行的存储过程。玩得开心。甚至不要考虑触摸桌子。


2

这是我整个职业生涯(近40年)以及编写DBMS时都遇到的问题。我的终点描述在这里:http : //unibase.zenucom.com。所以这是我的想法。

  1. 一般而言,大多数约束在应用程序中可以得到更好的处理,以便应用程序的不同部分可以实施不同的约束。例如,州代码可能不适用于所有司法管辖区。
  2. 顺便提一下%。标记> 100%或您破产了:)
  3. 最好用负面描述约束。即他们不能成为什么,而不应该成为什么。它总是一个更简单的列表。
  4. 外键总是好的,应该使用。句号。FK是RDBMS中为数不多的语义结构之一,非常有用。最大的困难是决定是否删除FK时让值悬挂,还是使用相关行作为不删除FK记录的原因。
  5. 现实世界中的约束通常比单个字段值约束更为复杂。
  6. 即使在应用程序级别,某些约束也会影响良好的操作。例如,积极的日期检查会在明显好的日期中隐藏错误。您需要操作员错误才能对在其他情况下合理的查找日期中的错误进行度量。

1

数据库约束可能是一个聪明的主意,但是对它们的实际使用又如何呢?考虑您的百分比约束。如果您采用这种方式,您的数据库将很乐意拒绝无效百分比。接着?您将需要业务逻辑来处理异常。这实际上意味着编写错误百分比的业务逻辑在其他地方已经失败。简而言之:剩下的唯一实际约束是您看到的约束(例如PK / FK)。


15
我对此表示不同意。如果您确实需要数据的一致性,则必须使用DB约束,尤其是在业务逻辑失败的情况下。他们用这种方式描述正在发生无声故障的情况,在这种情况下,错误百分比故障所造成的损害将在系统中进一步传播。如果您对此有数据库约束,那么您将很快失败,从而使业务逻辑开发人员有机会及早发现错误并修补业务逻辑系统,而不是允许损坏的数据进入其中。
马查多

5
我的理解是,如果违反了百分比约束,则不必处理此异常,因为这种违反表示首先代码中存在错误(有人使用简单的整数而不是Percentage类的实例,或验证本身有错误),而不是特殊情况(例如网络连接断开)。对我来说,违规行为应导致Web应用程序出现HTTP 500或桌面应用程序崩溃,然后应记录并修复该问题。
Arseni Mourzenko '16

7
@ThomasKilian:不 恰恰相反。不会输入错误的数据,特别是因为存在数据库约束。如果您的业务逻辑在代码中正确无误,那么您永远不会违反这些约束。如果代码中发生错误,则这些约束将使您警惕此错误,同时使数据库免受损坏。
Arseni Mourzenko '16

9
@ThomasKilian:我认为没有人反对“首先做到正确”-可能更多的是,只要有一点经验,任何人都知道在假设您会做一个系统的情况下设计系统是一个坏主意。第一次使一切正确,并且在系统的整个生命周期内都不会发生错误或错误。数据库约束确保错误或错误不会损坏数据库。
JacquesB '16

3
@JacquesB我正在与风车作战。如果将业务逻辑放在数据库中,则它一开始就可能失败,并且不能以同样的方式为您省钱。但是(!)您现在拥有不属于它的业务逻辑。认为数据库可以节省您的烂业务逻辑是完全错误的。数据库中的逻辑必须遵循与整个业务逻辑相同的规则。
qwerty_so

1

如今,人们越来越多地使用软件(例如Entity Framework)来自动生成表和列。他们的想法是他们不需要SQL技能,从而释放了大脑的能力。

人们对软件会“解决问题”的期望通常是不现实的,并且不会像人类那样产生约束。

为了获得最佳结果,请使用SQL创建表并手动添加约束,但是有时人们无法做到这一点。


当然,某些框架支持自动添加PK和FK(半)。
大卫·奥尔德里奇
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.