-
SQL Server引擎组件
SQLServer有四个主要组件:协议,关系引擎(也称为查询处理器)、存储引擎和SQLOS。来自任何客户端的应用程序,只要是交给SQL Server执行,都必须与这四个组件交互。
协议组件:用于接收请求,并把它们转换成关系引擎可以处理的形式。另外,协议层还获取所有查询的最终结果、状态消息或错误消息,并在将它们返回给客户端之前转换成客户端可以识别的形式。
关系引擎组件:用于接收T-SQL批处理任务,并确定如何处理它们。对T-SQL查询和编程结构而言,关系引擎层用于解析、编译和优化查询,并监督批处理任务的执行过程。执行批处理任务时,如果需要数据,获取数据的请求将传给存储引擎。
存储引擎组件:用于管理所有的数据访问,包括通过基于事务的命令和批量操作(如备份、批量插入)访问,以及特定的DBCC命令访问。
SQLOS组件:处理一些通常被认为是操作系统的职责,如线程管理(计划)、同步原语、死锁监测、内存管理及缓冲池。
一、协议层
应用程序与数据库引擎进行通信时,协议层公开的应用程序编程接口(API)使用Microsoft定义的表格格式数据流(TDS)包格式化通信信息。服务器和客户端计算机上的网络库使用标准通信协议(如TCP/IP或Named Pipes)封装TDS包。在通信服务端,网络库是数据库引擎的组成部分。在客户端,网络库是SQL本地客户端的组成部分。客户端的配置和SQL Server实例确定使用哪一个协议。
可以对SQL Server进行配置,使它同时支持来自不同客户端的多个协议。每个客户端使用单个协议连到SQL Server。如果客户端程序不知道SQL Server正在侦听哪个协议,可以配置客户端按顺序尝试多个协议。可以使用以下协议:
Shared Memory。它是最易于使用的协议,没有可配置设置。使用Shared Memory协议的客户端只能连接到在同一计算机上运行的SQL Server实例,因此该协议对大多数数据库活动没有作用。如果怀疑其他协议配置不正确,可以使用该协议进行故障诊断。使用MDAC 2.8或更早版本的客户端无法使用Shared Memory协议,如果试图进行连接,客户端将切换到Named Pipes协议。
Named Pipes。开发该协议旨在为局域网(LAN)提供服务。一个进行使用内存的一部分向其他进程传递信息,因此一个进程的输出是另一个进程的输入。第二个进程可以是本地的(和第一个进程在同一台计算机上),也可以是远程的(在网络计算机上)。
TCP/IP。TCP/IP协议是Internet上使用最广泛的协议。TCP/IP可以在采用不同硬件架构和操作系统的计算互联网之间进行通信。它包含一些用于路由网络流量的标准,并提供高级安全功能。在SQL Server上启用TCP/IP协议需要大量的配置工作,但大多数网络计算机上都已经正确配置了该协议。
Virtual Interface Adapter(VIA)。该协议与VIA硬件一起工作。这是一种专用的协议,可以从硬件供应商获取详细的配置信息。
表格格式数据流端点
SQL Server 2008还允许您创建TDS端点,以便SQL Server侦听附加的TCP端口。在安装过程中,SQL Server自动为所支持的4个协议中的每一个创建一个端点,如果启用该协议,所有用户都可以访问它。对禁用的协议而言,端点仍然存在,但无法使用。附加端点是为DAC创建的,只有sysadmin固定服务器角色可以使用DAC。
二、关系引擎
关系引擎也称为查询处理器。它包含的SQL Server组件用于确定查询需要完成的任务,以及如何实现才是最佳方案。关系引擎包含两个最主要的部分:查询优化(Query Optimization)和查询执行(Query Execution)。查询优化器(Query Optimization)也许是查询处理器中最复杂的组件,甚至是整个SQL Server产品中最复杂的组件,它用于确定批处理中查询的最佳执行方案。
另外,当关系引擎从存储过程中请求数据和处理返回结果时,它还管理查询的执行过程。关系引擎和存储引擎间的通信一般通过OLE DB行集(row set)实现(行集是OLE DB中的结果集术语)。存储引擎包含需要真正访问和修改磁盘数据的组件。
1.命令解析器
命令解析器用于处理发往SQL Server的T-SQL语言事件。它检查语法的正确性,并将T-SQL命令转换成可以进行操作的内部格式。这种内部格式称为查询树。如果解析器无法识别到语法,将立即引起语法错误,并标识出现错误的位置。不过,非语法错误消息不能明确显示引起错误的源行。因为只有命令解析器可以访问语句源代码,真正执行命令时,源代码格式中的语句将不再有效。
2.查询优化器
查询优化器从命令解析器中获取查询树,并为执行查询准备查询树。无法优化的语句,如控制流和数据定义语言(DDL)命令,将被编译成内部形式。可优化的语句将被做上标记,然后传递到查询优化器中。查询优化器主要涉及数据操作语言(DML)语句SELECT、INSERT、UPDATE和DELETE,这些语句可以按多种方式进行处理,查询优化器将从许多可能的方式中确定一种最佳方式。查询优化器将编译整个命令批处理,优化可优化的查询,并检查安全性。该查询优化和编译将产生一个执行计划。
产生该计划的第一步是规范每个查询,该过程可以将单个查询分解成多个细化的查询。查询优化器规范查询后,将对查询进行优化,这意味着它将为执行查询确定计划。查询优化时基于成本的:查询优化器基于内部指标选择消耗最少的计划,内部指标包括评估内存需求、CPU利用率和需要的I/O数目。查询优化器将根据请求语句类型,检查各种相关表中的数据量,查看每个表中可用的索引,然后查看查询中引用的每个索引或列的数据值采样。数据值采样名为分发统计信息。根据可用的信息,查询优化器分析查询中各种可用的访问方法和处理策略,并选择成本效益最高的计划。
查询优化器还使用修剪启发式算法,以确保优化查询的时间不会比简单选择并执行计划花费的时间长。查询优化器不需要执行详尽优化。某些产品考虑每种可能的计划,并选择成本效益最高的计划。详尽优化的优点是,无论用户使用什么语法,查询语法的选择在理论上不会引起性能区别。但使用复杂查询时,评估每种可能的计划花费的时间比接受并执行一个好计划(即使不是最好的计划)花费的时间要长得多。
完成规范化和最优化以后,这些过程产生的规范化树将被编译成执行计划。执行计划实际上是一种数据结构。执行计划中的每个命令精确指定了将涉及哪些表、将使用哪些索引(如果存在多个索引)、将检查哪些安全性,以及哪些条件(如等于某个特定值)在选择中的值必须为TRUE。这种执行计划表面上看似乎很简单,但其实内部过程相当复杂。除了实际的命令,执行计划还包括所有必须执行的步骤,以确保对约束条件进行检查。调用触发器的步骤与验证约束条件略有不同。如果操作行为中已经包含了触发器,还需要追加包含触发器的过程调用。如果触发器是instead-of触发器,触发器计划的调用将替换实际的数据修改命令。对after触发器而言,触发器计划在修改语句激化触发器之后和提交修改之前执行。与约束条件验证步骤不同的是,触发器的特定步骤没有编译到执行计划中。向含有多个约束条件的表插入一行的简单请求可以导致执行计划访问多个其他表,或者计算表达式的操作。另外,触发器的存在还可以导致更多步骤的执行。执行真正的INSERT语句的步骤也许只是整个执行计划的一小部分,但整个执行计划需要确保执行所有与添加一行相关的操作和约束。
3.查询执行器
查询执行器运行查询优化器产生的执行计划,在执行计划中充当所有命令的调度程序。批处理完成之前,该模块将逐步跟踪执行计划的每个命令。大多数命令需要与存储引擎进行交互来修改或检索数据及管理事务和锁。
三、存储引擎
SQL Server存储引擎包括涉及访问和管理数据中数据的所有组件。在SQL Server 2008中,存储引擎主要包括3部分:访问方法、锁定和事务服务及实用工具命令。
1.访问方法
SQL Server查找数据时,需要调用访问方法代码。访问方法代码建立并请求数据页和索引页扫描,并准备OLE DB行集来返回关系引擎。类似地,表插入数据时,访问方法代码可以从客户端检索OLE DB行集。访问方法代码含有对应的组件来执行打开表、检索合格数据和更新数据操作。访问方法代码实际上并不检索页面,它向缓冲管理器发送请求,最后缓冲管理器在其缓存中提供页面,或者将页面从磁盘读到缓存中。扫描启动时,预测先行机制将对页面上的行或索引条目进行鉴定。满足特定标准的行检索名为合格检索。不仅SELECT语句中可以使用访问方法代码,有些UPDATE和DELETE语句(如含有WHERE从句的UPDATE语句),以及需要修改索引条目的任何数据修改操作也可以使用访问方法代码。下面列出了一些访问方法类型。
行和索引操作。可以将行和索引操作看成时访问方法代码组件,因为它们执行真正的访问方法。每个组件分别负责操作和维护各自在磁盘上的数据结构(分别指数据行或B树索引)。它们理解并操作数据和索引页上的信息。
行操作代码用于检索、修改并执行单个行上的操作。它在一行中进行操作,如“检索第2列”或“将该值写入第3列”。在访问方法代码、锁及事务管理组件的协同工作下,需要的行被找到并被锁定(作为事务的一个执行部分)。在内存中格式化或修改行以后,行操作代码将插入或删除一行。如果数据时大型对象(Large Object,LOB)数据类型(如text、image或ntext),或者行太大无法在单个页面上显示而需要存储为溢出数据时,行操作代码需要处理特殊的操作。
索引操作代码维护并支持搜索B树,B树用于构造SQL Server索引。索引是一种树结构,含有根页面、中级页面和低级页面(如果树非常小,也许没有中级页面)。B树把含有相似索引键的记录进行分组,因此通过搜索关键值可以快速访问数据。B树的核心功能是能够平衡索引树(B代表balanced)。索引树的分支根据需要相互连在一起或拆开,因此对于任何给定记录的搜索,将始终遍历相同数目的级别,因而需要相同数目的页面访问。
页面分配操作。分配操作代码管理每个数据库页面的集合,并跟踪一些信息,如数据库中哪些页面已经使用了、为什么使用这些页面,以及每个页面上还有多少可用空间。每个数据库都是8KB的磁盘页面集合,这些磁盘页面分布在一个或多个物理文件中。
SQL Server使用13中磁盘页面。磁盘页面包括:数据页面、两种LOB页面、行溢出页面、索引页面、页面可用空间(PFS)页面、全局分配映射和共享全局分配映射(GAM和SGAM)页面、索引分配映射(IAM)页面、批处理更改映射(BCM)页面,以及差异更改映射(DCM)页面。
所有用户数据都存储在数据或LOB页面上,所有索引行都存储在索引页面上。PFS页面用于跟踪数据库中哪些页面可用于存储新数据信息。分配页面(GAM、SGAM和IAM)用于跟踪其他页面,它们不包含数据库行,并且仅在内部使用。BCM和DCM页面用于使备份和还原变得更加有效。
版本操作。版本存储是SQL Server 2005产品中添加的另一种数据访问类型。行版本允许SQL Server维护旧版本的更改行。SQL Server中的行版本技术支持快照隔离和SQL Server 2008的其他功能,其中包括联机索引结构和触发器。版本操作代码负责维护行版本。
2.事务服务
SQL Server的核心功能是能够确保事务是原子的——也就是说 ,全或无。另外,事务必须是持久ide,这意味着如果事务已经提交了,那么无论在何种情况下,都可以通过SQL Server进行恢复——哪怕整个系统爱确认提交后1毫秒出现故障。事实上,事务必须满足4个属性:原子性、一致性、隔离性、持久性,这称为ACID属性。
在SQL Server中,如果任务正在处理中,并且在提交事务之前出现了系统故障,那么所有工作必须回滚到事务开始前的状态。预写日志记录(Write-ahead logging)用于使处理中的任务回滚,或者使未应用到数据页中的提交任务执行前滚称为可能。在事务确认提交之前,预写日志记录能够确保在磁盘的事务日志中捕获每个事务记录的变化,并且在把真正发生变化的数据页写入磁盘之前,始终先在磁盘中写入日志记录。写入事务日志始终是同步的,即SQL Server必须等它们完成。但写入数据页可以是异步的,因为所有效果都可以根据需要在日志中进行重构。事务管理组件用于协调日志、恢复和缓冲管理。
事务管理组件描述形成某个操作而必须组合在一起的语句边界。它用于处理相同SQL Server实例中的跨数据库事务,并能处理嵌套事务序列(不过,嵌套事务仅在第一级事务环境中执行:提交嵌套事务时,不能出现特别的操作。低级嵌套事务中指定的回滚操作将取消全部事务)。对其他SQL Server实例(或对任何其他资源管理器)的分布式事务而言,事务管理组件使用操作系统远程调用来处理Microsoft分布式事务协调器(Microsoft Distributed Transaction Coordinator,MS DTC)服务。事务管理组件标记了保存点,在事务中通过保存点指示可以在此处部分回滚或取消任务。
根据实际的隔离级别,当锁可以释放时,事务管理组件还可以配合相关锁代码进行工作。它还可以配合版本代码确定何时不再需要旧版本,并且可以把它从版本存储中删除。事务运行的隔离级别确定了应用程序受其他程序影响的敏感度,因而页确定了事务应对这些变化所必须保持锁定或维护版本数据的时间。
SQL Server 2008支持两个并发模型来保证事务的ACID属性:乐观并发和悲观并发。乐观并发通过锁定数据来确保正确性和并发性,使数据不发生改变;SQL Server 2005之前的SQL Server版本都以独占方式使用这种并发模型,SQL Server 2005和SQL Server 2008在默认情况下页以独占方式使用这种模型。SQL Server 2005引入了乐观并发,它在名为version store的tempdb区域通过保留旧的行版本和已提交的值来提供一致性数据。在悲观并发中,读程序不会阻塞写程序,写程序也不会阻塞读程序,但写程序会阻塞写程序。实际操作中必须考虑这些非阻塞读取和写入行为的开销为了支持乐观并发,SQL Server需要花费更多的时间来管理版本存储。另外,管理员必须密切关注tempdb数据库,并计划为它提供特殊维护。
SQL Server 2008提供了5种隔离级别语法。其中仅3种支持悲观并发:未提交读、可重复读和序列化。快照隔离级别支持乐观并发。默认的隔离级别——已提交读——能够同时支持乐观并发和悲观并发,具体情况取决于数据库设置。
事务的行为取决于采用的隔离级别和并发模型。全面理解隔离级别还需要理解锁定的含义,因为它们使密切相关的。
锁定操作。锁定是多用户数据库系统(如SQL Server)中一个非常重要的函数,即便在快照隔离级别中使用乐观并发进行操作,该函数也非常重要。SQL Server允许您同时管理多个用户,并确保事务能查看选定隔离级别的属性。虽然在快照隔离中读程序不会阻塞写程序,写程序也不会阻塞读程序,但写程序仍然需要锁定,写程序可以阻塞其他写程序。如果两个写程序试图同时修改相同的数据,就必须解决冲突问题。锁定代码将获取和释放各种锁,如读取共享锁、写入独占锁、在更高粒度发出潜在“计划”执行某些操作的意向锁,以及供空间分配使用的扩展锁。它管理不同类型锁的兼容性,解决死锁问题,以及根据需要增强锁的功能。锁定代码用于控制表、页面、行和系统数据锁定。
3.其他操作
另外,存储引擎中还包含用于控制实用工具的组件,如大容量加载、DBCC命令、全文索引填充与管理,以及备份和还原操作。日志管理器确保日志记录的写入方式能保证事务的持久性和可恢复性。
四、SQLOS
SQLOS是一个单独的应用层,它位于SQL Server数据库引擎的最低层;SQL Server和SQL Reporting Services都在顶层运行。SQL Server的早期版本在存储引擎和实际操作系统之间使用廋接口层,通过该接口层,SQL Server可以调用操作系统来执行内存分配、计划资源、线程和工作管理,以及同步对象。不过,SQL Server中需要访问这些接口的服务可以位于引擎的任何部分。SQL Server需要管理内存、计划程序、同步对象等,因此任务变得越来越复杂。于是,Microsoft公司设计了单独的应用层来管理所有特定于SQL Server的操作系统资源,而不是让引擎的每个部分支持增加的功能。
SQLOS的两个主要函数是计划和内存管理。SQLOS包括的其他函数如下:
同步化。同步化对象包括spinlocks、mutexes和系统资源上的特殊读/写锁。
内存broker。内存broker用于在SQL Server中的各种组件之间分发内存分配,但不执行任何非配,分配由内存管理器处理。
SQL Server异常处理。异常处理涉及处理用户错误和系统产生的错误。
死锁监测。死锁监测机制不仅包括锁定,还包括监测任何占用资源的任务,这些任务相互阻塞。
扩展事件。跟踪扩展事件类似于SQL跟踪(SQL Trace)功能,但它更有效。因为与SQL跟踪相比,跟踪过程在更低级别运行。另外,因为扩展事件层的级别非常低,因此可以跟踪更多事件类型。SQL Server 2008资源调控器使用扩展事件管理资源使用率,
异步I/O。异步和同步的区别在于,系统的哪个部分实际用于等待不可用资源。SQL Server请求同步I/O时,如果资源不可用,Windows内核将把线程放入等待队列中,直到资源可用为止;对异步I/O而言,SQL Server首先请求Windows初始化I/O,接着Windows启动I/O操作,但不阻止运行线程,然后SQL Server把服务器线程放在I/O请求队列中,直到它从Windows获取资源可用的信号为止。