有一种说法称,“云计算不再是SQL的时代,而是NoSQL的时代”,因此,不依赖SQL且结构简单的NoSQL数据库受到了广泛的关注。那么,SQL数据库真的已经不再那么重要了吗?SQL数据库真的不支持云计算吗?

“云”的定义

“云”这个词有很多种用法,不过它的定义却非常模糊,导致我们的讨论容易过度发散。为了让论点更加明确,我们在这里将“云”定义为“大规模分布式环境”这个概念。

当然,“云”并非总是代表“大规模分布式环境”,但在数据库系统的语境中,用“云”这个词一般是代表现有数据库系统很难应对的情况。也就是说,数据量和访问量这两者的其中一个,甚至是全部两个,其规模已经超过单独一台数据库服务器所能够应对的程度,必须要依靠由多台服务器协同工作所构成的分布式环境来进行应对。 在这样的环境中,不使用SQL的NoSQL数据库很受欢迎。像SQL这样复杂的查询访问是受限的,取而代之的则是多个NoSQL数据库自动分布到多台服务器上的架构。这种方式对大规模分布式环境拥有更强的亲和力。

SQL数据库的极限

那么,SQL数据库真的不适合大规模分布式环境吗?在云计算环境中,它真的就不如NoSQL数据库吗?事实上并不一定。在云计算环境下最大限度利用现有SQL数据库的技术,目前已经在实用化方面取得了一定的进展。 其中一个基本的思路是对数据库进行分割。在专业领域,这种数据库分割被称为Sharding或者Partitioning。这种手法的目的,是通过将数据库中大量的记录分别存放到多台服务器中,从而避免数据库服务器的瓶颈。以“mixi”这样的社交网站(SNS)为例,可以理解为将用户编号为偶数的用户和编号为奇数的用户分别存放到不同的数据库中。这样就避免了对单独一台数据库服务器的集中访问,从而提高了处理速度。第一步的分割可以在应用程序级别上完成,在上述例子中,对编号为偶数和奇数的记录分别访问不同的数据库,而这样的逻辑可以编写在应用程序中。

不过,仔细想想就会发现,其实数据库的分割和应用程序逻辑的本质毫无关系,是需要在数据库层面上解决的问题。将这样的逻辑混入应用程序中的话,说实话是很“拙劣”的。数据库的问题,就应该在数据库中解决,不是吗?像这样能够实现自动分割的方法有很多种,这里我们介绍一下为MySQL提供分割功能的“Spider” 。

存储引擎Spider

Spider是由ST Global公司的斯波健德(Kentoku Shiba)先生开发的一种存储引擎。在MySQL中,用于查询处理的数据库引擎和实际负责存储数据的存储引擎是相互独立的,对于每张数据表都可以采用不同的存储引擎。可能大家都听说过“InnoDB”、“MyISAM”之类的名字,这些都是MySQL的存储引擎。 Spider和它们一样,也是在MySQL上工作的存储引擎的一种。不过,Spider自身并不执行实际的数据存储操作,而是将这些操作交给其他的MySQL服务器来完成。也就是说,在使用Spider的时候,表面上看起来是一个数据库,实际上却可以将数据自动分割保存在多台数据库中(sharding),而且只要对一台数据库保存数据,也会同时在其他服务器的数据库中保存(replication)。比起在应用程序端实现分割来说,用Spider来实现有下列这些优点:

  • 逻辑和数据库相分离:使用Spider,就意味着从应用程序端看起来,对数据库的访问和通常的MySQL访问是完全一样的。因此,在应用程序端不需要进行任何特殊的应对。
  • 可维护性高:和分割相关的信息都只维护在表定义中,而且,数据库分割策略也可以在表定义中进行设置。关于数据库的设置都集中在一个地方,这一点从可维护性的角度来说,是非常重要的。

刚才我们介绍了利用MySQL的存储引擎“Spider”进行自动分割的手法。其实实现自动分割的软件不仅只有这一种,单在MySQL数据库中,除了Spider之外,还有像“MySQL Cluster”、“SpockProxy”等其他方案。

SQL数据库之父的反驳

尽管通过Sharding技术将数据库进行分割,就能够在分布式环境中运用SQL数据库,但却无法做到像一部分NoSQL数据库那样,能够根据需要自动增加节点来实现性能的扩充。此外,如果用SQL数据库来实现NoSQL中这种简单的查询处理,大多数情况下在性能上(如每秒查询数)都不及NoSQL。

虽说SQL和NoSQL各自所擅长的领域不同,但很多人曾经认为“在大规模分布式环境中使用NoSQL是板上钉钉的事”。在这个时候,迈克尔?斯通布雷克(Michael Stonebraker,1943~)站了出来。斯通布雷克是最早的RDB系统Ingres的开发者,在Ingres商用化之后,他开发了Ingres的后续版本Postgres,后者演变为现在的PostgreSQL。斯通布雷克应该被称为“PostgreSQL之父”,但他的贡献并非仅仅如此。由于Sybase以及Microsoft SQL Server中都继承了他所开发的Ingres的代码,因此毫无疑问,他是一个对于SQL数据库整体都产生了巨大影响的人物。现在,斯通布雷克担任MIT(麻省理工学院)客座教授,同时还在几家数据库相关的企业中担任董事。

斯通布雷克在计算机协会ACM 的学术期刊《Communications of the ACM》(ACM通讯)2010年4月号中刊登了一篇题为“SQL Databases vs NoSQL Databases”的专栏 。在该专栏中,斯通布雷克以“所有的技术都有其擅长的领域,没有一种数据库是万能的”为前提,提出了以下观点:

  • NoSQL的优势在于性能和灵活性。
  • NoSQL的性能优于SQL这一说法,并非在所有情况下都成立。
  • 通常认为NoSQL是通过牺牲SQL和ACID特性 来实现其性能的,然而性能问题与SQL和ACID是无关的。

说实话,看了这些内容,我的第一反应就是:“唉?真的吗?”。作为像我这样写了很多文章,给别人灌输了“云计算时代非NoSQL莫属”观点的人来说,实在是百思不得其解。

那么我们就来看个究竟吧。根据这篇文章,决定SQL数据库性能的,是客户端与服务器之间的通讯开销,以及服务器上的事务处理开销。而通讯开销可以通过将大部分处理放在服务器上的“存储过程”(Stored Procedure)在一定程度上得以解决。

而对于服务器上的处理,大致进行分类的话,主要有4个瓶颈,而对于这些瓶颈的应对就是决定性能的关键。这4个瓶颈具体如下:

日志(Logging):为了防止磁盘崩溃等故障的发生,大多数关系型数据库都会执行两次写入。即向数据库执行一次写入,再向日志执行一次写入。而且,为了防止日志信息丢失(为了实现ACID中的D),必须保证这些数据确实写入了磁盘中。这样,即便由于一些问题导致数据库崩溃,也可以根据日志的内容恢复到故障前的状态。然而,考虑到向磁盘写入的速度是非常慢的,因此向日志执行确定的写入操作是非常“昂贵”的。 事务锁(Locking):在对记录进行操作之前,为了防止其他线程对记录进行修改,需要对事务加锁。这也形成了一项巨大的开销。

内存锁(Latching):Latch是门闩的意思,这里是指对锁和B树等共享数据结构进行访问时所需要的一种排他处理方式,斯通布雷克管这种方式叫做Latching。这也是造成开销的原因之一。

缓存管理(Buffer Management):一般来说,数据库的数据是写入到固定长度的磁盘页面中的。对于哪个数据写入哪个页面,或者是哪个页面的数据缓存在内存中,都需要由数据库进行管理。这也是一项开销很大的处理。

斯通布雷克认为,要实现高速的数据库系统,必须要消除上述所有4个瓶颈,而且上述瓶颈并非SQL数据库所固有的。听他这么一说,好像还真是这么回事。

NoSQL之所以被认为速度很快,是因为它在设计之初就考虑了分布式环境,通过多个节点将处理分摊了。然而,SQL数据库也是可以将处理分摊到多个节点上的。此外,即便是NoSQL数据库,只要涉及到磁盘写入操作,以及多线程架构下的缓存管理,也难以回避上述瓶颈中的一个或几个。

通过上面的分析,斯通布雷克的结论是,无论是SQL还是ACID特性,都不是影响云计算环境下数据库性能的本质性障碍。

本文摘自已经上市的《代码的未来》