第三十章 数据库是一个细节
从架构的角度来看,数据库是一个非实体——它是一个细节,没有上升到一个架构元素的层级。它与软件系统的架构之间的关系更像是门把手与你家的建筑架构的关系。
我意识到以上论述是有争议的。相信我,我已经纠结过了。所以让我清楚:我不是在谈论数据模型。你在应用程序中为数据提供的结构对于系统的体系结构非常重要。但数据库不是数据模型。数据库是一块软件。数据库是一个提供数据访问的实用程序。从架构的角度来看,这个效用是无关紧要的,因为它是一个低级细节,一种机制。一个好的架构师不允许底层机制染指系统架构。
关系数据库
Edgar Codd在1970年定义了关系数据库的原理。到1980年代中期,关系模型已经成长为数据存储的主要形式。这种流行有一个很好的原因:关系模型是优雅的,有规则的,强健的。这是一个很好的数据存储和访问技术。
但无论多么辉煌,有用,从数学上听起来是一种技术,它也只是一种技术。这意味着它一个细节。
虽然关系表对于某些形式的数据访问可能比较方便,但是将数据安排到表内的行中并没有体系结构上的重要性。你的应用程序的用例不应该知道也不关心这些问题。实际上,对数据表格结构的了解应限制在体系结构外层的最底层的工具函数中。
许多数据访问框架允许数据库行和表作为对象在系统周围传递。这种做法是一个架构错误。它将用例,业务规则以及某些情况下的UI耦合到数据的关系结构。
为什么数据库系统如此之前?
为什么软件系统和软件企业里数据库系统会占主导地位?Oracle,MySQL和SQL Server的优势是什么?总之:磁盘。
旋转磁盘是数据存储五十年的主流。几代人的程序员都不知道其他形式的数据存储。磁盘技术已经从直径为48英寸,重达数千磅,容量仅为20兆字节的巨大盘片堆积到直径为3英寸,重量仅为几克,容量超过TB的单个薄圆盘。这已经是巨大的飞跃了。但在整个过程中,程序员一直都被一个磁盘技术致命的缺点所困扰:磁盘的速度很慢。
在磁盘上,数据存储在圆形轨道中。这些轨道分为几个扇区,通常保存4K字节。每个盘片可能有数百个轨道,可以有十几个盘片。如果要从磁盘读取特定的字节,则必须将磁头移动到正确的磁道,等待磁盘旋转到正确的扇区,将该扇区的所有4K读入RAM,然后索引到该RAM缓冲区得到你想要的字节。而这一切都需要时间——毫秒级别的时间。
毫秒似乎不是很多,但是一毫秒比大多数处理器的周期长一百万倍。如果该数据不在磁盘上,则可以以毫微秒为单位访问,而不是毫秒。
为了减轻磁盘施加的时间延迟,你需要索引,缓存和优化的查询方案;而且你需要某种常规方式来表示数据,以便这些索引,缓存和查询方案知道正在处理的内容。总之,你需要一个数据访问和管理系统。多年来,这些系统分为两种不同的类型:文件系统和关系数据库管理系统(RDBMS)。
文件系统是基于文档的。文件系统提供了一个自然而方便的方式来存储整个文档。当你需要按名称保存和检索一组文档时,它们运行良好,但当你搜索这些文档的内容时,文件系统不会提供很多帮助。找到一个名为login.c的文件很容易的,但是找到有一个名为x的变量的内容的.c文件是很难也很慢的。
数据库系统是基于内容的。数据库提供了一种自然而便利的方式来根据内容找到记录。数据库非常善于根据记录共享的一些内容关联多个记录。不幸的是,数据库在存储和检索不透明的文档方面相当不友好。
这两个系统都将数据组织在磁盘上,以便根据特定的访问需求尽可能高效地存储和检索数据。每个人都有自己的索引和安排数据的方案。另外,每一个方案最终都会将相关的数据带入RAM中,以便得到快速地操作。
如果没有磁盘会怎样?
像磁盘曾经流行一样,它们现在是一个将死的品种。不久,他们将走上磁带驱动器,软盘驱动器和CD的道路。他们正在被RAM取代。
问问你自己这个问题:当所有的磁盘都没有了,所有的数据都存储在RAM中,你将如何组织这些数据?你会组织到表中,并用SQL访问它?你会组织成文件,并通过目录访问它?
当然不是。你将把它组织成链表,树,哈希表,堆栈,队列或其他无数的数据结构,你可以使用指针或引用来访问它——因为这就是程序员所做的事情。
事实上,如果你仔细想想这个问题,你会意识到这是你已经做的。即使数据保存在数据库或文件系统中,你也可以将其读入RAM,然后为了方便起见,将其重新组织到列表,集合,堆栈,队列,树或任何符合你想象的数据结构中。你不太可能以文件或表格的形式保留数据。
细节
这个现实就是为什么我说数据库是一个细节。这只是我们用来在磁盘表面和RAM之间来回移动数据的机制。数据库实际上只不过是我们长期存储数据的一个大桶。但是我们很少使用这种形式的数据。
因此,从架构的角度来看,我们不应该关心数据在旋转磁盘表面上的形式。事实上,我们不应该感知磁盘存在。
但性能呢?
性能不是一个架构问题吗?它是架构问题——但是在数据存储方面,这是一个可以完全封装并与业务规则分离的问题。是的,我们需要快速获取数据存储区中的数据,但是这是一个低层级的问题。我们可以用低层级数据访问机制来解决这个问题。它与我们系统的整体架构没有任何关系。
轶事
在20世纪80年代后期,我领导了一家创业公司的软件工程师团队,试图建立和销售一个网络管理系统,测量T1电信线路的通信完整性。系统从这些线路终端的设备中检索数据,然后运行一系列预测算法来检测和报告问题。
我们使用的是UNIX平台,我们将数据存储在简单的随机访问文件中。我们不需要关系数据库,因为我们的数据很少有基于内容的关系。这些随机访问文件中的树和链表更好。总之,我们把数据保存在一个最方便的形式,加载到可以被操作的RAM中。
我们聘请了这家创业公司的营销经理——一个好的和有知识的人。但他立即告诉我,我们必须在系统中有一个关系数据库。这不是一个选项,它不是一个工程问题——这是一个营销问题。
这对我来说没有意义。为什么在世界上,我想重新排列我的链表和树到一堆通过SQL访问的行和表?为什么当一个简单的随机访问文件系统绰绰有余时,我会引入大量RDBMS的所有花费和开销?所以这遭到我强烈地反驳。
我们在这家公司聘请了一位硬件工程师,负责RDBMS呗。他深信,由于技术原因,我们的软件系统需要RDBMS。他和公司的高管们一起举行了会议,在房子的白板上画了一个平衡杆的简单数字,他会问管理人员:“你会在一根柱子上盖房子吗?”他隐含的信息是:保持随机访问文件中的表的RDBMS比我们使用的随机访问文件更可靠。
我与他争辩。我与营销人员争辩。面对难以置信的无知,我坚持我的工程原理。我争辩,争辩,争辩。
最后,硬件开发人员被提升为我的领队,成为软件经理。最后,他们把一个关系型数据库放入这个可怜的系统。最后,他们是完全正确的,我错了。
不是出于工程原因,请介意:我是对的。我正确地反对将RDBMS融入系统的架构核心。我错的原因是因为我们的客户希望我们有一个关系数据库。他们不知道他们数据库用来干嘛。他们没有在我们的系统中使用关系数据的任何现实的方法。但是这并不重要:我们的客户十分期待RDBMS。它已成为一个必选项,所有的软件购买者的清单上都有。没有任何工程理由,理性不起作用了。这是一个非理性的,外在的,完全没有根据的需求,但事实如此。
这需求从哪里来?它起源于当时数据库供应商所采用的高效营销活动。他们设法说服高层管理人员说他们的企业“数据资产”需要保护,他们提供的数据库系统是提供这种保护的理想手段。
我们今天看到了同样的营销活动。“企业”这个词和“面向服务的体系结构”这个概念,更多的是市场营销而不是现实。
在那个很久以前的情况下我应该做些什么?我应该在系统的一侧安装一个RDBMS,并提供一些狭窄而安全的数据访问通道,同时将随机访问文件保存在系统核心中。但我实际做了什么?我退出并成为顾问。
小结
数据的组织结构,数据模型在架构上是重要的。但在旋转的磁性表面上移动数据的技术和系统不是架构上重要的。将数据组织到表中并用SQL访问的关系数据库系统与前者相比,更多地与后者有关。1数据库是一个细节。
1. Relational database systems that force the data to be organized into tables and accessed with SQL have much more to do with the latter than with the former. ↩