SQLServer内核架构剖析 (转载)

SQL Server内核架构剖析 (转载)

本文原贴出自:http://www.sqlserver.com.cn程序员

 

这篇文章在我电脑里好长时间了,今天不当心给翻出来了,以为写得很不错,所以贴出来共享。


不得不认可的是,一个优秀的软件是一步一步脚踏实地积累起来的,众多优秀的程序员呕心沥血,他们已经不是在简单的写代码,而是在创做一门艺术。sql

和前面提到的暴雪公司的发展相比他们有一个相同之处,即:他们只作经典。不能说他们集中的全世界最优秀的程序员,而实际上他们集中的是全世界最好的思想,而且付诸实践。数据库

成功不是靠急于求成,而是靠远见。祝Microsoft SQL Server越走越远。



咱们作管理软件的,主要核心就在数据存储管理上。因此数据库设计是咱们的重中之重。为了让咱们的管理软件可以稳定、可扩展、性能优秀、可跟踪排错、可升级部署、可插件运行,编程

咱们每每研发本身的管理软件开发平台。咱们老是但愿去学习别人的开发平台(如用友或金蝶或SAP),但咱们却老是感叹管理软件业务处理细节繁多,安全

而数据库管理软件却简单的SELECT、INSERT、DELETE、UPDATE四个命令就搞定性能优化

咱们多但愿有一天能作出一个架构,也能够这么简单就搞定管理软件。咱们每每研究别人的架构,却忘记了咱们身边咱们最熟悉的数据库的架构。服务器

因此,今天,我想带领你们一块儿剖析一下数据库的架构,来探索数据库的架构思想。而我本人呢,只熟悉SQLSERVER这一种数据库产品,因此我就拿SQLSERVER来分析。网络


在讲SQLSERVER内部原理的以前,我以为很是有必要向你们介绍一下SQLSERVER的历史
让咱们站在1999年,看看计算机数据库业界到底处于什么状态。
1999年,Oracle已经于1998年9月发布了Oracle 8i(可能中文版在1999年才来到中国)。架构

Oracle 8i支持用JAVA编写存储过程,支持XML,支持Linux。
1999年1月,SQLSERVER7正式发布。SQLSERVER7重构了整个数据库引擎(至关于重写了SQLSERVER)。 并发

SQLSERVER第一次完整性的支持了行锁(有没有搞错,过去人是怎么使用数据库产品的。1988年,Oracle6就支持行锁。另外1988年,Oracle就开始研发ERP产品。谁说Oracle是ERP门外汉,能够参考这个)。
看看他们俩的前一个版本。若是你入行比较晚(2000年之后),可能对如下文字更感到惊讶。
1992年Oracle7发布。有了存储过程、触发器、引用完整性校验、分布式事务处理。(天哪,Oracle7才有了这些东西)。
1995年,SQLSERVER6发布。SQLSERVER6是微软真正意义上的第一个数据库产品(真是爆料,你们没想到SQLSERVER6才是微软第一个数据库产品那版本6以前的五、四、三、二、1是怎么度过的)。

由于1994年,微软和Sybase掰了(Sybase是第一个运行于PC上的C/S数据库产品)。微软为了进入数据库产品领域,本身又没有经验,

因而和Sybase一块儿合做(当时微软是全世界第一大软件公司,微软1986年上市。Sybase有产品,缺钱。微软缺产品,有钱。因而一拍即合)。

直到1994年,微软也不须要Sybase了(已经学会了数据库技术),Sybase也感受微软太狼子野心,因而合做分裂。微软开始本身作本身的数据库。


历史说完。咱们言归正传。

不少入门级作管理软件的,SQL语句玩的熟练,从子查询到Having到交叉表统计SQL都能作出来,甚至存储过程能写2000多行,游标、自定义函数、触发器、约束用的眼花缭乱。

再入点门,在SQL查询器中可使用SQL分析优化索引,用SQL Profile能够跟踪SQL,甚至在性能查看器中监测SQLSERVER内存、CPU、线程、I/O的运行状态,甚至为本身会使用DBCC而沾沾自喜。


你是如此熟悉SQLSERVER,又是对SQLSERVER如此陌生。
我今天就用架构的角度来给你们分析一下SQLSERVER架构和原理。短短一篇博文确定只能面上的多一些,深一层的可能须要连载数篇文章甚至一块大砖头书才能讲完整。

不过,我但愿个人博文可以抛砖引玉,使你们能从一个过去没有想过的角度去看SQLSERVER。

 


SQLSERVER,做为一个数据库产品,我我的认为,最重要的就是两大块:存储引擎和查询引擎(关系引擎)。


其余的日志、事务、锁、索引等等都是围绕他们来工做的。

 

关系引擎(查询引擎)上层
SQLSERVER是C/S产品,因此一条SQL语句要让SQLSERVER执行,必需要传输到SQLSERVER服务器端。传输,咱们固然知道须要NetBEUI、TCP/IP等等网络传输协议。可是光有这些还不行。

客户端如何发,服务器端如何收,如何确认发的和收的正确完整,如何确实发的和收的已经结束,如何发和收能跨越各类网络协议(如UNIX和WINDOWS和NOVELL通信),如何保证数据安全校验,

如何保证数据收发是同步仍是异步,就须要在网络传输协议之上再构造一层协议。SQLSERVER既支持IPC机制(interior process call),也支持RPC机制(remote process call)。你想一想你的管理软件开发平台是否有这一层。

固然,如今的消息服务器已经专业的提供了这一机理,可靠的、安全的、高效的、异步的、消息压缩、消息拆分、智能路由、集群,跨越不一样的操做系统、不一样的编程语言、不一样的通信协议、不一样的硬件平台的消息数据传输。

 

可能你过去不了解消息中间件,经过这一案例能够知道消息中间件的用途。


SQL语句被可靠无误的发送到了服务器端,SQLSERVER引擎中第一个模块就来接待这个SQL数据。这个模块的名字叫:Open Data Services

它监听新的链接;清除失败链接;将结果集、消息和状态返回给客户端。

 


SQLSERVER客户端和服务器端之间传输数据,数据包是有格式的。在SQLSERVER中被称为tabular data stream

这个数据流是令牌控制客户端和服务器端对话(不然,客户端说了N句话,服务器端返回N句话,没有令牌就混在一块儿了,不知道哪一个回答是对应哪一个请求的)。

咱们每每不能直接和Open Data Services打交道,把数据放进来。而是咱们必须经过ODBC、ADO或DB-Library来发送tabular data stream。

 

而SQLSERVER返回的数据结果,也是经过这些ODBC之类发回tabular data stream。你看看SQLSERVER设计的多巧妙,一个通用数据访问接口屏蔽了你和SQLSERVER之间直接沟通

就如同WINDOWS API屏蔽了内核让你没法访问,就如同DirectX屏蔽了UI和外设的操控。

 


SQL语句-ODBC-编码成tabular data stream-IPC或RPC-网络协议-IPC或RPC-解码tabular data stream-ODBC-Open Data Services。
Open Data Services监测客户端链接。若是并发太多,它会建立链接,若是服务完,它会本身维护链接纳入池中。在池中保留一段生命期,它会本身释放链接

若是有的客户端链接中途忽然断掉(如客户端重启了),它在侦听后无回应发送keepalive数据包侦测是否死掉,它也会本身整理本身的链接的。

咱们在SQLSERVER线程中看到的链接,就是Open Data Services建立的。

 


Open Data Services有了链接(多是建立的多是从池里拿出来的,池化、建立、销毁都是很是讲究技能的

池化多少,上下文资源如何保留,池化多长时间,何时该销毁,调度不当就会严重消耗资源),就把SQL hang住。这时,是接到了Open Data Services的读缓冲区里面。

这个缓冲区为高性能处理数据的SQLSERVER带来一丝喘息机会,而就这一丝喘息机会,让SQLSERVER能够游刃有余(你的设计有吗?)。

而Open Data Services有一个写缓冲区。SQLSERVER把检索到的数据,检索出来就当即放进写缓冲区,写缓冲区一满就当即被Open Data Service发走。

当我过去研究SQLSERVER原理的时候,我经常赞叹,一个小小的SQLSERVER外围模块都设计如此精妙,实在让人佩服。咱们常常在追求海量数据存储和Cache架构,咱们却无视咱们手边的SQLSERVER。


SQL语句放到读缓冲区,SQLSERVER的查询引擎(关系引擎)就开始工做了。它老是在侦听这个读缓冲区
SQL语句遇到的关系引擎的第一个模块就是命令分析器。咱们在SQL查询分析器中看到的查询分析结果就是它的输出杰做。它来构造查询树。

首先是将你的SQL语句规范化(你想一想你写的软件代码,输入数据来了什么都无论就直接处理,连输入数据校验都没有,怎能稳定),不然之后的步骤将很差操做,若是你的SQL语句有语法错误,

这个查询树的构造就没法完成,因而中断。而要规范一个SQL语句,首先要从SQL语法库中抽取SQLSERVER现有支持的各类语法和函数,SELECT * 平展 ,字段访问权限校验
一旦构形成功,关系引擎的第二个模块就是命令优化器,来裁剪这棵树。一个SQL语句能够生成多种执行和优化的方案(若是你使用过那种SQL优化工具的话,你就能理解),

SQLSERVER会选择最节省内存、CPU利用率、I/O次数(I/O是性能优化最要命的地方,每每性能就瓶颈在I/O上)的那一种方案。

优化器会根据每张表的数据统计/统计信息(有时候你为了性能优化,必须定时期同步更新一下统计,不然优化就会有偏差)。

并且优化器也会根据查询树去选择合适的索引(若是使用索引代价大,它会自动选择全表扫描),优化器也会根据查询树知道先取哪些表的数据,

而后再内存中如何合并数据,以获得你想要的结果(有时候想一想优化器真伟大,你一个SQL过去,它须要在极短的时间内作多少事啊,为了能在极短期内肯定一个相对优化的方案,它也不可能穷举全部可能的方案,因此咱们作海量数据优化的时候,每每评估多种方案,而后修改本身的SQL语句以符合产生最优的方案)。

 

规范化、优化完SQL语句,就要产生执行计划了。SQL管理器负责执行计划的产生。由于你发过来的SQL语句多是一个SELECT,也多是一个INSERT或UPDATE。即便SELECT,

也面临着用户权限的限制(你若是设置过某一个SQLSERVER用户的对象权限和列权限,你就会明白)。而INSERT之类更新语句,又会涉及到权限、默认值、约束、表达式、主外键、触发器

一个优化完的SQL,具体要真正让SQLSERVER从内存或硬盘上把数据找出来或者更新回去,须要不少细节的步骤。
查询执行器来负责SQL的执行。由于SQL的执行要涉及到事务、锁、等待、CPU调度,内存页失效影响、I/O存取影响,因此查询执行器会协调不少其余模块,但各个模块来负责处理,

而查询执行器并不真正所有包办,不然让事务管理器、锁管理器、索引管理器、页面文件管理器、缓冲管理器、行管理器、日志管理器干嘛去。

查询执行器是查询引擎的最后一个模块,接下来的模块都属于存储引擎的范畴。因此,从上看,查询引擎最主要是构造SQL查询树、优化裁剪SQL查询树,根据查询树产生执行计划,而后协调执行查询树,

把结果返回去。


存储引擎  下层

而真正要把数据取出来或存进去,就须要存储引擎来工做了。
首先根据执行计划,要存取哪些数据页和索引页。这就是访问方法管理器(access methods manager)要作的事情。但其实真要打开这些页,还不是访问方法管理器本身要亲手干的。
亲手干这个活的是一个叫“缓冲区管理器”的模块。由于在硬盘上的数据是不可能计算处理的,必需要在内存中才能让CPU来计算。因此要存取那些数据页和索引页,就通知让缓冲区管理器来作。

若是数据没有在内存中,就让缓冲区管理器来读入,若是数据已经在内存中了,缓冲区管理器只有返回便可。这个过程是被缓冲区管理器来屏蔽的,对于访问方法管理器是透明的

你们可不要觉得访问方法管理器啥事不作,只是一个发布调度命令的。这可错怪了它。由于SQLSERVER要保证高速处理,必须预先预测好哪些数据页和索引页要处理。

不能人家缓冲管理器已经处理完,你访问方法管理器才计算下一步将要处理的页面。要知道,这些管理器但是不分哪一个用户来处理的。若是接受来自100多个并发的用户,发来各类各样的数据处理请求,

你怎么能预测到哪些数据页和索引页要处理呢?这就须要一个统一的调度。并且这个统一的调度也影响着缓冲区管理器。你不能请求一个大数据,缓冲区管理器这才火烧屁股才扩大缓冲区,而后装载数据,

那样流水线就停下了。缓冲区管理器必须预先知道将在不久要有一个大数据,因此在并行运算的时候就有独立线程来扩展了缓冲区。由于扩大缓冲区还和操做系统有关。

你要扩大缓冲区,正好遇到WINDOWS页面失效(缺页中断 page fault),就涉及到你的虚拟文件的变化。而页面失效又会影响CPU和I/O。因此页面失效是一个性能影响很大的问题。

而提升命中率是咱们性能优化一直努力的重点。若是数据长时间不用,缓冲区管理器就要让这块内存数据过时,能够被新的数据覆盖。不然缓冲区老加载不卸载也不行。

再说,有些数据已经被更新了,你数据老化了,不从新读入,你的数据就引发读错误了。


咱们知道,数据页包含数据行。索引页包含索引行。数据行就由行管理器来控制。而索引行,由索引管理器来负责。
而单行上的检索、修改、执行,又被事务管理器锁管理器影响着。事务,有显性事务和隐性事务两种。而锁,又有共享锁、排它锁、更新锁、意向锁。而锁,还分为行锁、页锁、表锁、数据库锁。

而锁,又有死锁的可能性。锁的不一样,加上事务的影响,这个行是否能读、能修改,能怎样的读(读一致仍是脏读),是等待事务和锁,仍是能够进行,就受了不少影响。

由于一张数据页上放的行是有限的,尤为还有填充度的影响(如填充度为80%,就这个数据页面只能填充80%就必须分页,以防之后有数据插入的时候,就很是影响数据插页,

这也是性能影响比较大,尤为在插入数据比较多的状况下)。SQLSERVER的一张数据页默认是8K,除去填充度和数据头,也没有多少可存储的数据了。

这就是为了关系型数据库都劝阻你们要小表大数据。也就是说,列要少,列要短,频繁访问的列要在前。数据能够海量。若是行长了,你想要检索和更新多少数据页,这须要多少页面调度,

面临着页面失效和锁机制的影响。并且,大文本和可变行,都是指针存储,须要跳转查找,更浪费了很多时间
而索引管理器,最主要在维护着索引B树。没有索引页,咱们就要作全表扫描了,那须要载入多少数据页,并且还要逐行扫描,若是赶上事务和更新锁,就更有问题。

因此,索引是很是重要的。而一个表,能够创建不少索引。索引,能直接找到所须要的行,而无须全表扫描。可是,你的索引若是仅仅是男女,或者你的索引涉及到可变行,都对索引不利。

索引,不宜创建多。不然维护索引页的成本和消耗也很是多。索引页更要涉及到插页、拆页,频繁改动涉及到索引的字段,会让索引页剧烈变更,尤为数据量越大影响越大。

我就不在这里讲解如何利用索引优化SQL了,不然一本书也讲不完。


数据不断存取,数据不断被维护,载入内存或从内存中写入硬盘。其实都是惰性写入器在照顾。惰性写入器来按期扫描老化数据,让硬盘和内存中的数据是一致的。

有这个惰性写入器,就有了内存和硬盘的差别时间窗。就有可能出现异常。一旦服务器忽然断电,没有来得及写会磁盘的怎么办。也也涉及到另外一个模块:日志管理器

日志管理器利用检查点的机制维护着日志文件。在服务器从新启动的时候,重写载入日志来把数据恢复到一致性。写日志,固然要比写数据要容易的多,快的多。

由于写数据要操控内存和硬盘,还要注意权限、锁、事务,因此忽然断电,你还没反应就来不及了。因此日志这种轻量级的方法,

就能够在恢复一致性上有很好的帮助(固然,也丢失数据。日志页也没来得及写入硬盘)。

 


讲到这里,就剩下事务管理器、锁管理器。这两个管理器和显性事务、隐性事务、显性锁、隐性锁、事务隔离级别、锁级别、行管理器、索引管理器都有不少关系。

 

 

微软有WINDOWS优点,又有Jim Gray这样的巨师坐镇(Jim Gray是图灵奖得到者,就是此爷提出了数据库事务这一律念。盖茨为了让此爷为微软工做,而此爷不喜欢雷德蒙每天下雨的天气,

因而在加州阳光中给此爷单独建了一座研究院  微软加州研究院)。

百度百科:http://baike.baidu.com/link?url=n0vbmC2FrrVB2xWyHFlQqntBeG9yOvX1zqrHYM6J9R0-xFAkjbnTuSh6Vh94c_m2yQ8nRdZAqD3V9llgVLVwxa

 

 

因此,在性能上,我我的认为SQLSERVER的性能是很是优秀的(你想一想,一个数据库产品的性能受什么方面的影响)。

至于业界老称SQLSERVER没法管理海量数据,性能不佳,我我的感受都是业界在以讹传讹而尤为中国内地IT业界,大部分都是入门级在跟帖嘈杂,尤为还有一批更不懂技术的媒体记者或写手


若是真要去说SQLSERVER不行,大型海量数据管理必须用某某数据库产品,我建议从内部原理、内部架构、内部实现三个层次诸多方面来剖析到底在不在理。


最后就是I/O管理器了。我一直不认同SQLSERVER内核中有I/O管理器。由于SQLSERVER使用的是和WINDOWS一样的页面调度和页面分配方法。

何须要本身另创一套呢。就如同SQLSERVER把页面、硬盘、内存、线程、CPU交给了WINDOWS同样。

SQLSERVER做为WINDOWS上的一个应用软件,应该和WINDOWS上的其余软件同样被WINDOWS管理。SQLSERVER又不跨平台,无须本身管理。
除了SQLSERVER这些内核涉及精妙之外,SQLSERVER的外围工具也设计的至关好。

如SQLSERVER的用户安全性管理方法、对象分类(表、列、约束、默认、索引、触发器、存储过程、视图、主键)、对象权限方法、元数据自管理方法、SQL语言、SQL查询分析器、SQL跟踪器、SQL性能分析器、SQL数据库(master\msdb\tempdb\model)。


想想,你的管理软件平台有这些架构思想吗?

http://blog.csdn.net/hzbooks/article/details/2247912

数据库界的超级牛人、1998年图灵奖得到才者Jim Gray先生于2007年1月28日早上独自乘船离开San Francisco Bay,去一个叫Farallon小岛洒他母亲的骨灰,不幸在外海失踪。直到如今也没有他的任何消息,美国海岸警卫队已经展开了大范围的搜索。 
 
计算机科学界的诺贝尔奖--图灵奖的评奖极为严格,不多在同一领域授予两人。所以图灵奖得主不只是做出了卓越贡献的超级科学家,也被公认为本研究领域的领袖。 做为计算机的传统主流方向,数据库只有三位图灵奖得主,都是大名鼎鼎的人物,开创了属于本身的时代。三巨头之一的E.F.Codd于2003年逝世,数据库之父Bachman也早已退休,离开了学术界,目前本研究领域硕果仅存的则只有Jim Gray一位:
 
Charles W. Bachman (1973) -- 数据库
Edgar Frank Codd (1981) -- 关系数据模型
Jim Gray(1998) -- 数据库和事务处理
 
数据库的教科书通常单独开一到两章来说解事务及其重要性,事务是数据库应用于银行,金融等行业的基础。信用卡刷卡,网上转帐这些操做都是做为数据库事务来完成的,事务机制保证了这些操做的正确性和完整性,从而获得普遍的应用。而提出事务概念和相关技术的,正是Jim Gray。此外,他仍是联机分析处理技术( OLAP)的奠定人,他提出了 Data Cube等重要概念。近十年来(并且可能一直延续到将来十年),
他一直是 数据库数据仓库数据挖掘等领域当之无愧的领军人物。
 
官方已经宣布Jim Gray 先生死亡。还会有奇迹出现吗?
 

2015-4-13 补充
事务管理 包含两个组件:一、锁管理器  二、事务日志管理器

Well I don't know whether writer wrote about Log manger or not but I would try to explain you

Storage engine of SQL Server has component called as Transaction Manager which manages locks for transaction an also manages transaction logs.

This Transaction manager has two components

1. Lock Manager

2. Log Manager

相关文章
相关标签/搜索