SQL Server的“高可用性”与“灾难恢复” 之二 故障转移群集

时间:2022-11-19 01:27:36

SQL Server使用最广的高可用性技术叫做故障转移群集(SQLServer Failover Cluster)。这是一项基于Windows故障转移群集的一种技术。SQLServer故障转移群集技术集成了微软技术一贯简单易用的特点,在部署和管理上都非常容易,同时又能提供非常良好高可用性,因此目前得到了非常广泛的使用。可以说,它是SQL2012之前的各个版本,实现高可用性的必选技术。

故障转移群集

要了解SQL Server故障转移群集,首先要对Windows故障转移群集有一个基本的了解。下面介绍的内容不求面面俱到地都覆盖Windows群集的知识,但对于一个数据库系统管理员,理解这些概念是非常有用的。

1.  Windows故障转移群集的基本组成要素

Windows故障转移群集是由多个服务器组成的。每个服务器也被称为“节点”(Node),每个节点上都运行着Microsoft 群集服务 (MSCS)。这些节点有相同的软硬件配置,并且具有共享的磁盘(Shared Array)。所有需要在几个节点之间共享的东西,例如SQLServer的数据库文件、错误日志等,都会被安放在共享磁盘上。不需要共享的内容则被安放在每个节点的本地磁盘上。

除了共享磁盘之外,组成群集的多个节点之间通过“私有网络”(privatenetwork)和“公共网络”(public network)连接起来。每个节点上有一块私有网卡,这些网卡通过网络互相连接组成了私有网络。节点之间通过私有网络互相发送信号来感知彼此是否已经工作正常,这类信号被称为“心跳线”。一旦某服务器因为某种异常而无法回应信号,这就好像一个人的心跳停止了一样。此时剩余的节点就认为这个节点已经“死了”,于是就把这个节点排除出当前群集。

公用网络,顾名思义是用来被群集外部的资源所使用的一个网络。每个节点上有一块公共网卡,外部资源通过公用网卡来访问这个节点。要注意的是,私有网卡和公共网卡在物理上可以是一块网卡,这种时候群集就通过一个网络来完成私有网络和公共网络的职责,这个网络被称其为混合网络(mixednetwork)。

一个群集内的所有节点共同组成一个“虚拟”的服务器(VirtualServer)。也就是说,从这个群集的外部来看,只能看到一个服务器,而不是它背后的一堆节点服务器。虚拟服务器具有自己的机器名和IP地址,而这个名称和IP与群集内的任何节点都不同。由于服务器是虚拟的,因此人们称呼它的IP是“虚拟IP”,而它的机器名是“虚拟网络名”(virtualnetwork name)。但事实上“虚拟IP”和“虚拟网络名”都是在DNS服务器上登记在册的,它们本身和一台真实的物理机器的IP和机器名没有任何区别,只是它们对应的服务器是一个虚拟的机器。虚拟IP一定要和公共网络配置在同一个网段里,因为这个IP需要在网络上可以被其他机器访问到。

在Windows群集中,虚拟IP,虚拟网络名,共享磁盘,SQL Server等等,被统称为“资源”。在任意时刻,只有群集中的一个节点能提供用户所需的服务和资源,而其他节点都处于空闲状态。所以,Windows群集无法提供负载均衡的能力。这个技术和NLB是有本质区别的。

那么当用户使用虚拟IP或者虚拟网络名来访问虚拟服务器的时候,到底是哪个节点来为用户提供服务呢?答案是,由“活跃节点”来提供服务。所谓的活跃节点,就是当前拥有该群集资源的节点。

举个例子,假设当前有两个节点,分别是NodeA和NodeB;它们组成的群集的虚拟网络名是Vserevr。在某个时刻,NodeA拥有了虚拟网络名和虚拟IP这两个资源,而服务器B拥有了一个共享磁盘资源DiskX。这种情况下,对虚拟网络名和IP而言,NodeA就是活跃节点,而对于共享磁盘DiskX而言,NodeB才是活跃节点。如果你使用远程桌面工具去连接虚拟网络名Vserver,你实际上是登录到了NodeA上,你可以的本地磁盘上的文件其实是NodeA磁盘中的文件,你运行的程序都是NodeA上安装的程序。虚拟网络名好像一个中转站一样,所有该虚拟服务器的请求都被转向到了NodeA上。但是NodeA上看不到共享磁盘。因为共享磁盘资源当前被NodeB所拥有。您只有直接登录到NodeB上才能看到那个共享磁盘。

谁是“活跃节点”是Windows群集服务决定的,对用户完全透明。用户不需要关心当前哪个节点正在运行。客户端的连接指令始终都是一样的:指向虚拟IP,或者虚拟网络名。例如用户要通过UNC方式访问共享磁盘上的某个文件,他所发出的指令会是\\Vsever\DiskX\FolderY\

 

2.  故障转移

接下来再来谈谈群集的“故障转移”(Failover,也称为“切换”)。也就是说,当“活跃节点”服务器出问题的时候,群集服务是怎么实现其“高可用性”的。

还是前面的这个例子,假设此时NodeA拥有DiskX,虚拟网络名和虚拟IP地址三个资源。如果NodeA突然间由于硬件故障蓝屏了,那么Windows群集会立刻探知到这个问题,然后自动发起一个故障转移。转移完成后,这三个资源全部在NodeB上线,也就是被NodeB所拥有。如果之前有一个用户通过\\Vsever\DiskX\FolderY\这样的UNC方式来访问共享磁盘上的某个文件,NodeA的蓝屏对该用户不会造成任何的影响。用户甚至可能没感觉到虚拟服务器内部的故障转移。对他而言通过Vserver里的那个文件一直都是可以访问,而这就是高可用性的目的。

除了由于系统故障所造成的Windows群集的自动切换,系统管理员也可以通过工具或者命令行手动发起切换。

 

故障转移群集

所谓的SQL Server故障转移群集,就是将SQLServer部署在Windows群集中的多个节点上,然后组成一个虚拟的SQLServer实例。这样SQL Server 实例依旧像运行在单台计算机一样显示在网络中。不过它具有一种功能,即在当前运行SQLServer实例的节点不可用时,可以在节点之间进行故障转移,把SQL Server切换到工作正常的节点上去继续为应用程序提供服务。

实现这个功能,需要将SQL Server安装成群集模式,而不是单机模式。安装的具体步骤,请参见本书的第一章。安装成功以后,您就可以看到本节所提到的各个管理界面了。

打开Windows的故障转移群集管理器(FailoverCluster Manager),然后使用Windows群集的虚拟网络名来连接群集。左侧的面板中的“Servicesand application”节点,下面会列出该Windows群集的所有“资源组”。“资源组”顾名思义就是由一个或者多个资源组成的组。所有的故障转移都是以资源组为单位发生的,在任何时候,每个资源组都仅属于群集中的一个节点,这个节点就是该资源组的“活跃节点”。由于资源组里的资源是一起切换的,所以这些资源应该是彼此关联,并且协同工作来提供某项服务。用户应当尽量避免把无关的资源加入到同一个资源组里。可以简单地把资源组想象成在虚拟服务器上运行的一个个独立的应用程序或者服务,而群集技术为这些应用程序或者服务提供了高可用的特性。SQLServer资源组就是一个很好的例子。

SQL Server群集资源组的结构

 

1.  SQLServer网络名和SQL Server IP地址

SQL Server群集并不使用Windows群集的虚拟网络名和虚拟IP地址来作为应用程序访问它的接口。在SQLServer的资源组里有该SQL Server实例自己专用的虚拟网络名和IP地址这两个资源,它们提供了应用程序访问SQL Server时使用的机器名或者IP地址。事实上,无论是Windows群集还是SQL Server群集的虚拟机器名/IP,它们的资源类型都是相同的,只是它们一个服务于Windows虚拟服务器;一个服务于SQL Server群集实例。

 

2.  SQL Server和SQLServer Agent

这两个资源是SQL Server故障转移群集的关键资源。它们分别代表了SQL Server服务和SQLServer Agent服务。事实上,SQL Server 2005群集还包含有第三种资源:SQL Server Fulltext Search。但是这个资源在SQL Server 2008以后被并入了SQL Server资源里,因此就只剩下现在这2个资源了。

对于一个SQL Server群集,群集中的所有节点上都会有安装有SQL Server和SQLServer Agent服务以及与服务所对应的二进制文件、注册表键值等。Node1是SQL Server的“活跃节点”。如果你到群集中的每个节点上的SQLServer Configuration Manager里查看的话,会发现只有Node1上的SQL Server实例对应的服务是处于启动状态,其余所有节点上服务都是处于停止状态的。

如果SQL Server是默认实例的话,那么SQL Server资源的名字就是“SQLServer”。如果SQL Server是命名实例的话,SQLServer资源名就是“SQL Server (实例名)”。客户端应用程序就是通过“虚拟网络名\实例名”的形式找到它所想要访问的SQLServer实例。

 

3.  共享磁盘

共享磁盘资源可以是一块逻辑磁盘,也可以是一块磁盘上的一个mountpoint。

对于一个SQL Server群集实例,数据库的所有数据文件和事务日志文件(MDF,NDF和LDF),SQL Server和SQLServer Agent的日志文件(ERRORLOG),以及一些其他的文件和目录,都是保存在共享磁盘上的。必须设置共享磁盘和SQLServer资源在一个资源组里,这样就保证了运行SQL Server服务的节点一定能访问到共享磁盘里的数据。

事实上SQL Server资源和共享磁盘资源是具有“依赖”关系的。也就是说在磁盘资源无法在某节点正常运行的时候,SQL Server资源在该节点也无法上线运行。

需要注意的是,一个共享磁盘资源只能属于一个SQLServer实例(事实上,在安装SQL Server群集实例时是不允许把SQLServer安装在一个已经被其他SQL Server群集实例使用的共享磁盘上的)。但是一个SQLServer群集实例可以使用多个共享磁盘。

 

4.  其他

除了上述列出的资源之外,SQLServer资源组里还可能包含

(1)  FileShare:如果 SQL Server要使用FileStream,就需要这样一个资源

(2)  AnalysisServices:这个资源和SQL Server/SQL Server Agent资源不同,是属于Generic Service资源。

 

一般而言,每个资源可能处于的状态有:

上线(online):该资源在某个节点上正常工作中。

离线(offline):该资源在某个节点上处于停止工作状态,无法提供相应的服务。

失败(failed):该资源在某节点尝试上线,但是由于某些异常无法上线成功。

上线挂起(onlinepending):资源尝试进入上线状态,但是还没完全成功上线。

离线挂起(offlinepending):资源尝试进入离线状态,但是还没完全成功离线。

以上五个状态中,上线/离线/失败是会长时间保持的状态;除非有人为的操作或者系统异常发生,否则他们会保持这个状态。而两个“挂起”的状态不会长时间保持。经过一段时间之后,它们要么成功“上线”,要么由于某种错误或者由于超时最后进入了“失败”状态。

2. 集群资源的配置

在任意一个资源上点右键,选择“属性”,在弹出窗口上能看到一系列选项卡,这里包含了群集资源的重要设置选项。

这里以SQL Server资源为例。首先来看“Dependencies”选项卡。

SQL Server资源的Dependencies属性页

这里显示了SQL Server依赖了哪些资源。SQLServer要依赖的资源包括:

·        虚拟网络名资源

·        共享磁盘资源

这两个资源之前的关系是“and”,就是说只有两个资源都online之后,SQL Server资源才可以online。这也符合SQL Server成功启动的要求:(1)能绑定IP地址,(2)能找到系统数据库和错误日志。

如果去看虚拟网络名的依赖“选项”卡,你会发觉它其实是依赖于虚拟IP资源。这样就组成了一个完整的依赖“链条”。SQL Server资源组里各个资源的依赖关系如下:

SQL Server资源组中属性的依赖关系

一个资源所依赖的其他资源必须要和这个资源处于同一个资源组里,跨资源组的依赖关系是不存在的。如果用户需要SQLServer群集实例同时可以访问多个共享磁盘资源,必须在SQL Server资源组里添加,然后让SQLServer资源去依赖于它们。没有这样的依赖关系,SQL Server群集实例将无法看到或者使用这些磁盘。

再来看“Policies”选项卡。

SQL Server资源的Policies属性页

这个选项卡里的选项决定了该资源发生故障转移时的行为。下面介绍一些推荐的设置:

1)  对于SQL Server资源组里的以下类型的资源:

·        SQL Server资源

·        共享磁盘资源

·        虚拟IP地址资源

·        虚拟服务名资源

都建议在策略选项卡里保留其默认设置。即确保If resource fails, attempt restart on currentnode 被选中并选择Ifrestart is unsuccessful, fail over all resources in this service or application。这样的设置下,上面的资源如果因为软件或硬件故障进入失败状态,会在15分钟内尝试在当前节点重启(一般就是立刻尝试重启,不需要等15分钟那么长),第一次尝试重启失败的话,就会将整个资源组故障转移到另外的节点上。这样的设置被称为“affectthe group”。

2)  出于最大化高可用的目的,对以下资源:

·        SQL Server Agent资源

·        File Share资源

·        Analysis Services资源

建议设置为选择 If resource fails, attempt restart on current node选项,并且不选择If restart is unsuccessful, failover all resources in this service or application 选项。这样设置下,上述资源如果由于软硬件异常进入失败状态,并不会导致整个资源组的切换,这些资源不会“affectthe group”。对于这些不是非常关键的资源,通常都建议配置成不“affect the group”,这样可以消除那些不必要的故障切换发生,提高数据库服务器的在线时间。千万不要把那些和SQL Server实例无关的资源加入到SQL Server资源组来,并且把它们配置为“affectthe group”,因为这样会大大提升SQL Server资源组发生无谓切换的风险。

最后,来看一下“Advanced Policies”选项卡。

SQL Server资源的Advanced Policies属性页

该选项卡中的“possible owners”部分会列出该资源可以切换到哪些节点上运行。SQLServer资源可以在Node1或者Node2上(这说明,在安装SQL Server群集的时候,SQL Server被部署到了这两个节点上)。如果任意节点前没有打钩的话,就意味着资源不能在这个节点上上线运行。

在这个选项卡里还有两个重要的选项。一个是“Basic resourcehealth check interval”,另外一个是“Thorough resource healthcheck interval”。Windows Cluster为了每个资源是否工作正常,会使用不同的时间间隔来做的两种不同程度的检查。我们通常把Basicresource health check俗称为“looks alive check”,而把Thorough resource health check称为“isalive check”。我们会在下面一小节里详细介绍这两种检查。

 

群集什么时候会发生“故障转移”

SQL Server故障转移群集是如何检测到系统故障,从而触发故障转移群集的呢?

前面说到过,Windows群集是通过做“looksalive check”和“is alive check”这两种不同的检查来判断资源是否工作正常的。如果检查失败,则判定该资源出现异常,然后就按照该资源的“Policies”选项卡里中设置,来进行故障转移。

群集里的每个资源都是一种资源类型。比如,共享磁盘的资源类型是physicaldisk,虚拟IP的资源类型是IP address,SQL Server资源对应的资源类型名字就叫“SQL Server”。根据不同类型的资源,会使用不同的方式进行isalive和looksalive检查。

资源类型、资源DLL和资源的关系

对于physical disk, IP, network name和DTC这类Windows群集自带的资源类型,它们各自的isalive和lookalive方法都定义在一个Windows群集自带的resource DLL “clusres.dll”中。对于那些非自带的资源(比如说SQLServer),如果它们有自己专属的资源类型并且有专属resource dll,就可以在resource DLL中定义自己的isalive和looksalive检查方法。有些资源没有特定的资源类型,我们称这类资源的资源类型为“通用服务”(Generic Service)。对于Generic Service类型的资源,Windows群集依旧使用clusres.dll来作为它们的resource dll。Clusres.dll里有针对Generic Service的“标准”isalive和lookalive检查方法。Windows群集服务进程clussvc.exe会产生名为RHS.exe的进程,RHS.exe会装载resource dll,并且调用dll中定义的方法来检查相应resource的状态。一个资源其属性的AdvancedPolices选项卡中如果没有勾选“run this resource in a separateResource ”,它的resource dll就会装载在一个默认的RHS.exe中;反之,则会有一个单独的RHS.exe来装载该资源的resourcedll。所以在任务管理器中你可能看到多个RHS.exe进程。

在安装SQL Server的时候,会安装两个SQLServer自己的resource dll :sqsrvres.dll和sqagtres.dll,它们分别服务于SQLServer资源和SQL Server Agent资源。一般只会把SQLServer资源配置成affect the group模式,因此要了解SQLServer群集什么情况下会故障转移,就要了解sqsrvres.dll是怎么定义looksalive和isalive方法的。事实上,从SQL Server 2000到SQL Server 2008 R2,sqsrvres.dll中定义的looksalive和isalive方法都是类似的。具体来讲:

Looksalive:通过服务控制管理器(Service ControlManager,简称SCM)来检查SQL Server服务在活跃节点是否处于“启动状态”。根据SQLServer资源的Advanced Polices选项卡中的设置,这个检查默认是每5秒钟做一次。

Isalive:根据SQL Server资源的Advanced Polices选项卡中的设置,这个检查默认是每60秒钟做一次,也就是说每12次Looksalive检查就会伴随一个Isalive检查。SQL Server需要Isalive检查,是因为即使SQL Server服务是正在运行状态,也不能说明SQLServer就可以良好地响应应用程序的请求。有的时候可能整个SQL Server已经挂起了,但是服务的状态还是“启动”。所以需要Isalivecheck来进一步检查SQL Server的状态。此外,一旦lookalive检查的结果失败,Windows群集服务就会立刻触发Isalive检查。

在SQL 2012之前,Isalive所做的事情很简单,Windows群集服务会使用TCP/IP或者Named Pipes来连接SQL Server群集实例。连接上之后,运行一句命令“select @@servername”。如果该语句成功返回结果,那么Isalive检查就成功了。

如果连接不上SQL Server群集实例或者语句运行失败,那么Isalive检查失败。此时Windows群集会再做3-5次(根据Windows的版本和设置不同)Isalive检查。如果这些检查都失败了,就要根据Policies选项卡中的设置开始进行故障转移。

您可以把故障转移简单地想象成SQL Server服务的重启,所不同的是故障转移的时候,SQL Server服务是在当前节点停止,然后在另一个节点上启动起来。因此故障转移所花费的时间和SQLServer服务重启的时间是差不多的。当然共享磁盘和虚拟网络名等资源在另一个节点上线也会额外花费一点时间,不过在大多数情况下这部分时间是比较短的。另外,由于故障转移一般是意外发生的,所以您要预期SQLServer切换到新节点以后,还需要一段时间来做数据库的recovery。

前面也提到过,除了SQL Server和SQLServer Agent以外,SQL Server资源组里可能还会有AnalysisService资源。但是和SQL Server/SQL Server Agent不同的是,Analysis Service资源没有自己的资源类型,也就是说它是一个GenericService(通用服务)。Analysis Service的isalive和looksalive检查就使用的是clusres.dll中定义的通用服务检查方法。

SQL Server的诸多服务和组件中,SQL Server、SQL Server Agent以及Analysis Service这三个服务,无论是有自己专属的资源类型还是通用服务,都是被设计为可以通过resource dll形成群集资源。这种类型的服务被称为cluster-aware。SQLServer还有很多其他资源,比如SQL browser, Reporting Service等,它们被设计成无法通过任何resource dll在Windows群集中形成资源,所以它们不是cluster-aware的。对于不是cluster-aware的服务,即使被安装在了群集的节点上,Windows依旧把它当成是安装在了一个单机环境中,它无法具有故障转移的功能。

需要提一下的是Integration Services是一个比较特别的服务。Integration Services本身不是cluster-aware的服务,但是用户可以通过一些步骤手动把它配置成一个群集资源。但是这样配置出来的Integration Services群集资源不是一个真正的资源,是不具有自动故障转移功能的,因此微软并不推荐这么做。更多的信息可以参考下面两篇技术文章:

·        http://msdn.microsoft.com/en-us/library/ms345193.aspx

·        http://support.microsoft.com/kb/942176

 

群集的拓扑结构

最简单的SQL Server故障转移群集拓扑结构就是“活跃/非活跃”群集。这种结构下群集有2个节点,用户在群集上安装一个SQL Server群集实例,该实例的“可能的所有者”(possibleowners)包含上述两个节点。这样任意时间只有一个节点上有SQL Server服务在运行,而另一个节点就是“非活跃”节点。这种配置的优点是结构简单明了,无论SQL Server运行在哪个节点上都能获得同样的性能表现。缺点是总有一个节点处于空闲状态,浪费了50%的硬件资源。

“活跃/非活跃”群集

另一种拓扑结构是“活跃/活跃”群集。还是以一个2节点的群集为例。这个时候用户在群集上安装两个SQLServer群集实例,每个实例的“可能的所有者”都包含群集两个节点。在正常情况下,两个实例分别运行在不同的节点上。这样两个节点就都是“活跃”节点。

“活跃/活跃”群集

这种结构的优势是两个节点的硬件资源都能被充分利用,节约成本。缺点是,一旦某个节点发生故障转移,就会发生另一个节点上同时运行了两个SQLServer实例的情况。此时,这两个实例可能会争用这个节点上的CPU,内存,I/O等资源,导致两个实例的性能都受到影响。有时候可能两边的用户都不能接受。因此要尽快解决异常节点上的问题,尽早把发生故障转移的实例切换回去。

在此基础上,我们来介绍所谓的N+1结构,即N个活跃节点加上1个非活跃节点。以3个节点的群集为例,在上面安装两个SQL Server群集实例,每个实例的possibleowner包含群集中的两个节点,但是只有一个节点是两个实例共有的。在正常情况下,两个SQL Server都运行在非共有的那个节点上,互不干涉。一旦某个节点发生故障转移,就会切换到那个共有的非活跃节点上。

N+1群集

这个结构是一个介于“活跃/非活跃”和“活跃/活跃”之间的一种方案。相对于“活跃/非活跃”,它浪费的节点资源比较少(1/N+1)。另外,两个以上的节点同时发生故障转移,需要同时切换到共有节点的概率是比较低的,因此也在一定程度上解决了“活跃/活跃”结构的性能问题。

无论什么样的拓扑结构,有两点是不会变的:

1.  SQL Server群集无法提供数据库端的负载均衡功能。作为“活跃/活跃”群集,其实是几个独立的数据库实例,它们彼此间没有联系。再次强调,群集技术只是一个提供”高可用性”的技术,而不是提升性能的技术。

2.  无论群集有几个节点,对于某个数据库实例,它只有一份数据。一旦数据本身出现问题,群集对此无能为力。所以,群集技术不是一个提供数据“灾难恢复”的技术。对重要的数据库,仅仅使用群集技术是不够的。

SQL Server 2012对故障转移群集的改进

SQL Server 2012群集基本沿袭了SQL Server2008群集以来的一系列特点。不过它也带来了一些新特性,使得群集具有了更加强大的功能以及更高的可用性。现在就让我们来看看SQLServer 2012群集都有哪些新东西。

1. 多子网群集的支持

从Windows Server 2008开始,故障转移群集开始支持所谓“多站点(multi-site)群集”。也就是说,组成一个群集的节点可以被安置在相隔很远的不同的站点。此外,不同站点可以处于不同的子网,因此多子网(multi-subnet)群集也得以实现。在地理上相隔很远的站点进行群集有时被称为拉伸群集(Stretch Clustering)。

对于一个多子网的群集,需要为群集里的每个站点都配置一个虚拟IP地址,而“虚拟网络名”资源会依赖所有这些IP地址资源。当群集运行在某个站点上时,只有对应该站点子网的虚拟IP地址资源可以处于上线状态,其余IP地址资源由于在该子网内无法被成功分配,因此都会处于“失败”或“离线”状态。从Windows Server 2008群集开始,用户可以把虚拟网络名资源配置成以“OR”的关系来依赖这些IP地址资源。因此即使只有一个IP地址可以上线,“虚拟网络名”资源也可以成功上线。可以说是,WindowsServer 2008群集对OR依赖关系的支持,是实现多站点和多子网群集的一个关键。

可是,虽然Windows Server 2008群集支持多子网,SQL Server 2008和SQL Server2008 R2群集却并不支持多子网。这是因为SQL Server 2008本身不支持OR的依赖关系。从SQL Server 2012开始,相应部分遗留的代码得到了重写,因此SQLServer支持多子网群集的障碍也得到了扫除。目前,只有运行在Windows Server 2008 R2群集上的SQL Server 2012群集才完全支持了多子网的功能。

在SQL Server 2012中,如果SQLServer发现“虚拟网络名”资源所依赖的某个IP地址不能上线,就会在SQLServer的错误日志中记录以下信息:

SQL Server could not listen on IP address [156.69.72.165]because the cluster resource ‘SQL IP Address 2 <inst>’ is not online(state=3). This is an informational message and may indicate that resource ‘SQLNetwork Name (CHSU-SQL2)’ has OR type of dependency on several IP addressessome of which are currently offline or in a failed state. Further action is onlyrequired if it is generally possible to bind the IP address of the clusterresource ‘SQL IP Address 2 <inst>’ to a network segment on the currenthosting node.

这条信息清楚的显示了IP地址[156.69.72.165]的状态,并说明了SQL Server没有绑定该IP地址。

对于成功上线的IP地址,错误日志中依旧会记录SQLServer绑定该IP的信息。该信息和之前版本的SQLServer是一样的:

Server is listening on [10.22.13.16 <ipv4> 60362].

以下是使用多子网的 SQL Server故障转移群集的一些示例配置:

·        SQL Server群集 包括 Node1 和 Node2。 节点1连接到Subnet1。 Node2 连接到 Subnet2。 SQL Server 安装程序将此配置视作一个多子网群集,并且将 IP地址资源依赖关系设置为 OR。

·        SQL Server群集包括 Node1、Node2 和 Node3。Node1 和 Node2 连接到 Subnet1。 Node3 连接到 Subnet2。SQL Server 安装程序将此配置视作一个多子网群集,并且将 IP 地址资源依赖关系设置为OR。 因为 Node1 和 Node2 位于同一子网上,所以此配置还提供本地高可用性。

·        SQL Server群集包括 Node1 和 Node2。 Node1 连接到Subnet1 上。 Node2 同时连接到 Subnet1 和 Subnet2 上。 SQL Server 安装程序将此配置视作一个多子网群集,并且将 IP 地址资源依赖关系设置为OR。

·        SQL Server群集包括 Node1 和 Node2。 Node1 连接到Subnet1 和 Subnet2。 Node2 也连接到 Subnet1 和 Subnet2。 SQL Server 安装程序将 IP 地址资源依赖关系设置为 AND。要注意,这种配置不被视作多子网故障转移群集,因为群集的节点实际上是处于完全相同的子网环境中。

我们所讨论的多子网SQL Server只限于IP地址资源依赖关系是OR的情况,即各个节点彼此处于不同的子网环境,多个IP地址不能在一个节点上全部上线的情况。

SQL Server 2012对多子网的支持,使得它更加适用于部署多站点群集。使用多子网的SQLServer群集,即使某个子网由于网络设备的突然故障而整体瘫痪,也能通过故障转移使用其他子网中的节点继续运行数据库服务,因此在抵御网络故障上具有更强的能力。多子网的SQLServer群集在地理上分散,使得它能更好地抵御例如自然灾害,大规模停电等重大异常。此外,多子网的群集不是在有所有节点间共享数据存储,所以需要在多个子网之间进行硬件存储器级别的数据复制,这样就获得了多个可用数据的副本。因此在硬件支持的前提下,多子网SQLServer群集除了具备高可用性之外,还提供了数据灾难恢复解决方案。

2. RegisterAllProvidersIP

多子网的SQL Server一般情况下,一个虚拟网络名对应多个IP地址,而只有其中一个IP地址资源是上线状态的。那么在DNS上到底是只注册了那个上线的IP地址,还是全部IP地址都注册了呢?这取决于“虚拟网络名”资源的一个私有属性,叫做RegisterAllProvidersIP。

如果RegisterAllProvidersIP被设置为0,那么只有上线的IP地址会被注册到DNS上,网络名也只会被解析到上线的IP地址。这看起来没什么问题,但是在发生故障转移的时候可能会带来一些麻烦。假设群集发生了故障转移,从一个子网中的节点切换到了另一个子网中的节点。当故障转移完成后,SQLServer资源组中的虚拟网络名没有发生变化,但是开始启用新子网中的IP地址。这时,客户端需要知道新的IP地址,才能连上SQL Server。这通常要借助DNS服务器。但是DNS服务器上的缓存可能会造成DNS的更新延迟,在一段时间之内DNS服务器依旧会将服务器名解析成之前的IP地址(即老的子网的IP地址)。于是在这段时间里,即使SQL Server已经恢复运行,连接SQL Server的请求还是会由于无效的IP地址而失败,这会增加客户端应用恢复到SQL Server的连接所需的时间。事实上,为了避免这类问题,WindowsServer 2008 R2群集在虚拟网络名资源上线的时候会立刻给DNS服务器发一个注册请求,目的就是尽快将服务器名指向新的IP地址。不过如果在DNS服务器端发生任何延迟,影响注册请求的完成,那么在这一段时间内,访问SQLServer的请求还是会受到影响的。

为了彻底避免DNS更新延迟带来的问题,SQL将虚拟网络名资源的RegisterAllProvidersIP的默认值设置为1。也就是说默认情况下,无论这个IP地址处于什么状态,多子网的群集依旧会在DNS 服务器上注册虚拟网络名到所有IP地址之间的解析关系。当客户端应用要使用虚拟网络名来连接SQLServer的时候,它会从 DNS 服务器检索所有已注册的IP 地址,并尝试连接到这些地址。这样,多子网SQL Server群集中的客户端恢复连接的时间不再受DNS 更新延迟的影响。

默认情况下,客户端会按顺序去尝试DNS上所有IP 地址。 当客户端在其连接字符串中使用MultiSubnetFailover=True 参数时,客户端会改为并行地尝试所有IP 地址,并使用第一台响应它的IP地址来连接SQL Server服务器。这样的机制有助于在发生故障转移时最大程度地减少客户端恢复连接的延迟。目前,只有以下驱动支持在进行TCP连接时使用MultiSubnetFailover参数:

·        SQL Native Client 11.0

·        .NET Framework 4.02 或更高版本中的SQLClient(必须在连接字符串中指定数据库实例的 TCP 端口)。

·        Microsoft JDBC Driver 4.0 for SQL Server

对于其他的驱动,你无法在连接字符串中使用MultiSubnetFailover 参数,也就是说它们只能顺序去尝试所有IP地址。这增加了遇到连接数据库超时错误的风险。因此,对那些访问多子网SQL Server群集的客户端,建议在连接字符串中适当地增加连接超时的阈值。通常情况下的建议是:资源组中每增加一个IP地址资源,就增加 21秒的连接超时。 这样,客户端在尝试重新连接SQLServer时,它会有足够的时间来依次访问所有 IP 地址。

3. 存放数据库的物理位置

SQL Server 2005 以前版本的SQL Server 故障转移群集,数据库的所有数据文件和日志文件都必须被放在共享磁盘上,包括用户数据库和系统数据库。

SQL Server 2008和SQL Server 2008 R2将系统资源数据库(resource DB)与其他的系统数据库分隔开来,单独存放在了每个实例对应的Binn目录下,和其他的SQL Server可执行文件和DLL文件放在了一起。这是因为resource 数据库是只读的不可修改的,它仅是用来提供SQLServer所有的系统对象,因此从功能上来看resource数据库更接近一个SQLServer的DLL而不是一个系统数据库。因此SQLServer 2008和SQL Server 2008 R2的群集中resource数据库的文件是存放在本地磁盘上,而不是共享磁盘上。

从SQL Server 2012开始,除resource数据库以外的所有系统数据库(master,msdb,model和tempdb)及用户数据库不但可以被存放在共享磁盘中,也可以被存放在共享文件夹中。如果你的SQLServer 2012群集使用共享文件夹来存放数据库,你必须使用“\\Servername\ShareName\...”这样的通用命名约定 (UNC) 路径格式。不可以使用环回路径(loopbackpath,例如 \\localhost\.. \)、管理共享(adminshare,例如 \\servername\x$)或映射网络驱动器。共享文件夹可以位于Windows文件服务器或第三方 的SMB(Server MessageBlock) 存储设备承载。 如果使用 Windows 文件服务器,该Windows 文件服务器版本应为 2008 或更高。

相比较共享磁盘,共享文件夹有三个主要的优点:

1.  免去了为共享磁盘配置SAN或者iSCSI等一系列繁琐的操作步骤。

2.  节省了SAN存储硬件。你可以使用任何存储器来提供共享文件夹。

3.  使用共享磁盘,一个Windows群集上可以安装的SQL Server 群集实例的数量取决于可用驱动器号的数量(无论是否使用mountpoint)。 如果只对操作系统使用一个驱动器号,则最多只能有 25 个SQL Server 实例。使用共享文件夹的话,就可以突破驱动器号数量的限制,在一个Windows群集上可以安装最多50个SQL Server群集实例。

你会发现在安装的过程中,安装程序并不强制要求你必须选择一个共享磁盘。显示了两个可用的共享磁盘,但是你可以两个都不勾选。

在指定数据库存在位置的步骤中,你就可以使用共享文件夹了。

 

SQL Server 2012群集的另一个变化是tempdb存放的位置。之前版本的SQL Server群集,要将所有用户数据库和系统数据库,包括tempdb,都保存在共享磁盘上。这样能确保所以节点都使用同一份数据。故障转移后无论哪个节点变成活跃节点,它所访问的数据都是一致的。但是tempdb是一个特殊的数据库,它在每次SQL Server启动时都会被重新创建。也就是说,故障转移后新的活跃节点得到的永远是一个新的tempdb,它不包含任何以前存在于tempdb中的数据。因此tempdb数据库其实不需要被群集的节点所共享。

SQL Server 2012群集允许用户在安装时将tempdb的存放位置设置在本地磁盘上。这样当SQL Server资源组在某个节点上线时,就会在该节点的本地磁盘上创建新的tempdb的数据文件和日志文件。除了tempdb和资源数据库以外的其他数据库依旧存放在共享磁盘或SMB文件共享上。

你可以发现SQLServer 2012群集的安装程序中多了Temp DB directory和TempDB Log directory这两个文本框,它们允许你为tempdb单独设置区别于其他数据库的存放路径。

将tempdb存放在本地磁盘可以节约共享磁盘的空间。另外,tempdb上一般会发生较多的I/O操作,所以将tempdb存放在本地磁盘还可以减轻共享磁盘的负载,有助于提高其他数据库的I/O性能。

如果将tempdb存放在本地磁盘的目录中,你需要确保群集中的所有节点上都有这个目录并且SQLServer的启动账号对这个目录有读写权限。否则一旦发生故障转移,SQL  Server就可能会因为无法创建tempdb而不能上线。

4. 新的ResourceDLL

前面介绍过SQL Server群集使用两种检查方式来确保群集正常工作并在需要的时候触发故障转移。一种是looksalive检查,它仅是简单的去检查活跃节点上SQL Server服务是否还在运行。另一种是Isalive检查,它是由群集服务开启一个连接到SQL Server里,并执行语句select@@servername,根据语句是否成功执行来进一步判断SQL Server是否依旧在正常提供服务。

很多情况下SQL Server发生故障转移就是由Isalive检查失败所触发的。管理员在故障转移发生以后,需要检查SQL Server日志和Windows系统日志,以了解为什么Isalive检查会失败,当时SQL Server出了什么问题。但是,很大一部分故障转移产生的原因是SQL Server当时出现了性能问题,以至于无法响应Isalive检查。很多性能问题,如CPU使用率100%,工作线程用尽,都不会记录在错误日志中。由此带来的问题就是,数据库管理员能从群集日志或Windows的事件日志中判断出SQL Server当时可能发生了性能问题,但无法得知具体是什么样的性能问题,于是也就无法采取措施来防止问题再次发生。

有时候SQL Server性能问题并不是十分严重,而且可能在很短的时间内就能自动恢复。用户可能不希望在这种情况下,Isalive检查失败就立刻触发故障转移。但是旧有的Isalive检查没有提供客制化的接口,用户或管理员无法自己指定SQLServer发生故障转移的场景。

SQL Server 2012群集使用了全新的Resource DLL(名字依旧是sqsrvres.dll)。新的Resource DLL中,Looksalive检查基本保持了其原有的功能,但是Isalive检查方式发生了变化。新的Isalive不仅依赖检查群集服务和SQLServer之间的连通性来判断SQL Server的健康状况,它还依赖SQLServer内部进行自我诊断,并将诊断结果报告给Resource DLL。总的来说,新的ResourceDLL有四个特性:

·        旧的Resource DLL在每次执行Isalive检查时生成一个连接到SQL Server,执行完select @@servername后就关闭连接,直到下次执行Isalive检查时再建立新的连接。而新的Resource DLL会在SQLServer资源上线后就始终使用一个独立的线程来维持一个到SQL Server的持续连接,连接不会中断,直到SQL Server资源进入离线状态。

·        新的Resource DLL改为执行一个全新的存储过程 “sp_server_diagnostics”来执行Isalive检查,判断服务器健康情况。Sp_server_diagnostics会收集SQLServer当前的诊断信息并返回给resource DLL并记录在扩展事件日志中,缺省情况下sp_server_diagnostics每20秒运行一次。SQL Server 2012群集的Isalive检查就依赖sp_server_diagnostics返回的信息来判定SQL Server是否工作正常,默认Isalive检查间隔依旧是60秒。可见,这种检查比仅运行select@@servername要可靠很多。

·        新的Resource DLL允许用户自己指定发生故障转移的条件。一旦Isalive或Looksalive发现SQL Server实例处于不健康的状态,那么resource DLL就会将当前的健康状态与用户指定的故障转移条件做对比,决定是否应该发生故障转移。客户可以根据系统的要求,设置什么情况下SQL会做故障转移。

·        Resource DLL会保留一段时间的sp_server_doagnostics历史诊断信息。这些信息可以更有效地帮助管理员找到发生故障转移的原因。

Resource DLL会根据SQL Server资源名到注册表里查询SQL的版本信息,以决定当前的SQL实例是否是2012版本,是否使用新的扩展功能。这意味从SQL Server2012开始,管理员不能轻易更改SQL Server的资源名,否则就可能会发生Resource DLL找不到该实例的版本、造成SQLServer资源不能上线的问题。

 

因为SQL Server资源类型使用了新的resourceDLL,你会发现SQL Server资源有了一些新的私有属性。


其中大部分属性在以前版本的SQL Server群集中都存在,它们的作用也没什么变化。这里我们重点介绍下新的resource DLL引入的两个新属性。

FailureConditionLevel

SQL Server 2012群集定义了从0到5总共6个级别的故障转移条件。用户可以通过设置SQLServer资源的FailoverConditionLevel属性来指定SQLServer在满足何种条件下发生故障转移。对于级别 1-5,每个级别除了自己的条件外,还包括之前级别的所有条件。这意味着,级别越高,故障转移或重新启动的几率就越大。 下表(2-1)介绍了这些故障条件级别:

 

级别

名称

条件

0

无自动故障转移或重新启动

  • 无论发生任何故障,都不会触发故障转移或重新启动。 但是诊断信息依旧被记录在LOG文件夹中的SQLDIAG文件里。此级别仅适用于系统维护目的。

1

服务器关闭时进行故障转移或重新启动

当满足以下条件时将触发服务器重新启动或故障转移:

  • SQL       Server 服务停止。

2

服务器不响应时进行故障转移或重新启动

当满足以下任意条件时将触发服务器重新启动或故障转移:

  • SQL       Server 服务停止。
  • SQL       Server 实例不响应(Resource DLL 在       HealthCheckTimeout 设置时间内未收到来自       sp_server_diagnostics 的数据)。

3

出现严重服务器错误时进行故障转移或重新启动

当满足以下任意条件时将触发服务器重新启动或故障转移:

  • SQL       Server 服务停止。
  • SQL       Server 实例不响应
  • sp_server_diagnostics       返回“系统错误”。

4

出现中等服务器错误时进行故障转移或重新启动

当满足以下任意条件时将触发服务器重新启动或故障转移:

  • SQL       Server 服务停止。
  • SQL       Server 实例不响应。
  • sp_server_diagnostics       返回“系统错误”。
  • sp_server_diagnostics       返回“资源错误”。

5

对于任何合格的故障条件进行故障转移或重新启动

当满足以下任意条件时将触发服务器重新启动或故障转移:

  • SQL       Server 服务停止。
  • SQL       Server 实例不响应。
  • sp_server_diagnostics       返回“系统错误”。
  • sp_server_diagnostics       返回“资源错误”。
  • sp_server_diagnostics       返回“query_processing 错误”。

表2-1 FailureConditionLevel的定义

级别3是FailureConditionLevel的默认值,它最接近于老的Isalive检查的故障转移条件。你可以随时更改FailureConditionLevel的级别,不需要重新启动SQL Server就可以立刻生效。从上面的表格你能看到,sp_server_diagnostics所返回的诊断信息对于判断是否应当发生故障转移是至关重要的。在下一节我们会详细介绍sp_server_diagnostics。

HealthCheckTimeout

这个属性决定了 resource DLL 在认定 SQL Server 实例不响应之前应等待服务器返回sp_server_diagnostics诊断信息的时间。HealthCheckTimeout的默认值是60000毫秒。

一旦SQL Server群集资源上线了,resourceDLL就会使用max(5, (HealthCheckTimeout/3))来获得一个sp_server_diagnostics的运行时间间隔。也就是说sp_server_diagnostics的查询时间间隔是(HealthCheckTimeout/3),但不会短于5秒钟。一旦运行时间间隔确定下来,resource DLL就建立连接到SQLServer,并发出语句sp_server_diagnostics<运行时间间隔>。有了<运行时间间隔>这个参数,sp_server_diagnostics就会按这个间隔自动地去不断获取诊断信息并使用那个持续的连接将信息返回,无需resource DLL反复去执行sp_server_diagnostics。

Max(5, (HealthCheckTimeout/3))不但是sp_server_diagnostics的运行间隔,也是它的查询超时时间。一旦sp_server_diagnostics在这个时间范围内无法获得返回结果,那么就产生超时错误,然后开始一次新的sp_server_diagnostics查询。因此,默认设置下resource DLL在认定SQL Server发生性能问题或宕机问题前,会尝试执行并等待三次sp_server_diagnostics。

而resource DLL连接SQLServer的连接超时是被硬编码为30秒的。不过,在达到HealthCheckTimeout所规定的超时时间之前,resource DLL会不断尝试去连接SQLServer。

对于SQL Server性能慢或者宕机的问题,在没有配置生成dump的情况下,群集的最长响应时间就是(Isalive检查的时间间隔+HealthCheckTimeout)。如果是SQL Server服务停止之类的问题,群集的最长响应时间就是Looksalive检查的时间间隔。

 

5. SP_SERVER_DIAGNOSTICS

前面已经多次提到了SQL Server 2012引入的新存储过程sp_server_diagnostics和它扮演的重要角色。这里我们具体看一下这个存储过程会提供怎样的信息。

Sp_server_diagnostics是一个标准的SQLServer存储过程。除了群集的会自动调用它来获得诊断信息之外,你也可以通过任意的SQL Server客户端工具(如SQL Server Management Studio)来直接使用它。

Sp_server_diagnostics只有一个参数 – “重复间隔”。如果不指定这个参数,则Sp_server_diagnostics返回一次诊断信息就结束了。一旦指定了这个参数,sp_server_diagnostics会根据这个间隔时间不断返回诊断信息。重复间隔时间不能小于5秒,因为sp_server_diagnostics需要约5秒钟才能返回结果。之所以需要5秒钟,是因为存储过程需要一段时间的连续运行来生成某些诊断信息。

sp_server_diagnostics是用来判断SQL Server健康状况、触发故障转移的重要存储过程,为了确保该存储过程的健壮性,保证它的运行不会受到服务器运行状况的干扰,SQLServer 2012数据库引擎为这个存储过程做了特别的优化:

1.  工作线程一旦开始运行该存储过程就会切换到抢占模式(preemptivemode)。

2.  工作线程的OS优先级会被提升,高于普通的SQLServer线程。

3.  该存储过程所需要的内存会被事先分配好。

4.  存储过程输出的内容被限制为每行256KB。

由于这个存储过程会被频繁地执行,因此其设计目标是不会给SQL带来超过0.1%的额外负载。SQL Server会维护一个全局列表用以记录所有正在运行sp_server_diagnostics语句的线程,另外安排SchedulerMonitor定期的去检查这些线程,一旦发现某个线程没能在30秒内完成一次sp_server_diagnostics的执行,Scheduler Monitor就会产生一个SQL Server进程的内存转储(dump)。分析这个dump能够帮助你理解为什么sp_server_diagnostics执行的这么慢。

下面让我们来看一个sp_server_diagnostics的示例输出:

输出的结果分为5行,每一行代表一个“组件”。也可以认为是一种分类:

·        System:从系统角度收集有关spinlock、运行过程中产生的严重错误、发生non-yielding问题的任务、页面错误和CPU 使用情况的数据。 

·        Resource:从资源的角度收集有关物理和虚拟内存、BufferPool、页面、缓存和其他内存对象的数据。 

·        query_processing:从查询处理的角度收集有关工作线程、任务、等待类型、CPU密集型会话和正在阻塞的任务的数据。 

·        io_subsystem:收集有关 IO 的数据。 。

·        Events:通过服务器记录的相关错误和事件中的存储过程收集数据,包括有关环形缓冲区异常、有关内存broker 的环形缓冲区事件、内存不足、计划程序监视、缓冲区池、spinlock、安全和连接的详细信息。 

输出结果最后一列是以XML形式记录下来的当前SQLServer的运行数据,包含了非常多的信息,对于判断SQL Server性能慢或宕机问题的根源非常有用。SQLServer利用内部的算法来处理这些数据,然后评估出一个运行状态。运行状态有4种:未知(unknown),干净(clean),警告(Warning)和错误(error)。

要注意的是,只有system,resource和query_processing这三个组件会有“错误”运行状态。这三个组件的运行状态被用做故障转移的条件(从第3级到第5级的FailureConditionLevel)。

下表(2-2)显示了每个组件可以得到的运行状态:

组件

干净 (1)

警告 (2)

错误 (3)

未知 (0)

system

resource

query_processing

io_subsystem

Events

表2-2 sp_server_diagnostics输出组件可能出于的运行状态

可以看到,io_subsystem 的状态只可能是干净或警告,它不会得到错误状态;而Events永远只有未知这一种状态。

2.2.6故障转移群集的故障排查

SQL Server 群集的故障排查主要是针对两类问题:

·        SQL Server资源无法上线

·        SQL Server意外发生故障切换。

这里提供一个排查这两类问题的大致思路,以供参考。

针对SQL Server资源无法上线的问题,首先要了解SQLServer资源上线的两大基本要素:1)SQL Server服务本身是否可以在该节点启动;2)Windows群集服务是否可以成功完成isalive检查,即可以成功连接SQLServer,并且运行sp_server_diagnostics语句。

所以,要排查SQL Server资源无法上线的问题,您可以根据这样的顺序来检查:

1)  在故障转移群集管理器中,确保SQL Server资源所依赖的资源都可以上线。如果任何资源不能上线,则去Windows事件日志中去查看是否有对应的错误和警告信息,然后做进一步的排查。

2)  如果所有依赖资源都可以上线,那么到当前节点的本地磁盘中找到SQLServer实例的Binn目录下的sqlservr.exe文件。然后用命令行启动SQL Server。具体的步骤可以参见SQLServer的联机丛书:

http://msdn.microsoft.com/zh-cn/library/ms180965.aspx

如果SQL Server启动失败,就可以到共享磁盘的LOG目录里找到SQL Server的错误日志ERRORLOG,看看ERRORLOG里有没有可以帮助排查问题的信息。如果不幸的ERRORLOG没有产生出来,那么就再到Windows事件日志中去查看是否有错误或者警告信息。

3)  如果SQL Server可以通过命令行启动起来,就说明问题出在Windows群集连接SQLServer并执行sp_server_diagnostics的过程中。这个时候可以先使用Sqlcmd等工具来连接通过命令行模式启动起来的SQL Server(记得要使用Windows验证)。如果出现连接错误或者认证错误,那么问题就转换成了一个纯粹的连接认证问题。

4)  如果sqlcmd可以成功连接,那么问题很可能与Kerberos/NTLM认证方式有关系。由于WindowsServer 2008群集服务的启动账号是Local System,因此当Windows群集通过TCP/IP或者Named Pipes协议去做Isalive检查时,实际上是使用了一个机器账号去连接SQLServer。由于连接SQL Server所使用的用户不同,有可能出现用sqlcmd做连接测试时没问题,但是Windows群集连接出问题的情况。这种情况下问题一般都是Kerberos或者NTLM认证的问题,导致最后isalive检查失败。在后面的第七章我们会更具体的介绍Kerberos和NTLM。

如果SQL Server资源意外的发生了故障转移,则需要去分析故障转移的根本原因。此时,您至少需要收集以下信息:

1)  Windows群集的日志。

这个是最重要的日志,通过它可以发现:

a.  SQL Server资源所依赖的资源是否发生了问题并进入了失败状态。如果是的话,那么SQLServer资源的故障转移完全是由于它所依赖的资源造成的,和SQL Server本身无关。

b.  SQL Server资源组里是否有任何被配置“affectthe group”的资源发生了问题并触发了整个资源组的故障转移。如果是这样的话,那么SQL Server就完全是一个受害者。

c.  是否有任何信息表明Windows群集无法完成对SQL Server的isalive检查。根据isalive检查失败的原因不同,信息的内容也会有所不同,这有助于你定位问题。总的而言,isalive失败的原因是两大类(1)Windows群集找不到SQLServer实例,(2)SQL Server出现性能问题无法响应Windows群集的连接请求或者无法成功执行sp_server_diagnostics命令。无论是何种原因,你一般都能看到类似下面的错误信息:

00000a04.00000e3c::2011/08/03-14:23:38.719ERR  SQL Server <SQL Server>:[sqsrvres] CheckQueryProcessorAlive: sqlexecdirect failed

00000a04.00000e3c::2011/08/03-14:23:38.719ERR  SQL Server <SQL Server>:[sqsrvres] printODBCError: sqlstate = 08S01; native error = 40; message =[Microsoft][SQL Native Client]Communication link failure

00000a04.00000e3c::2011/08/03-14:23:38.719ERR  SQL Server <SQL Server>:[sqsrvres] OnlineThread: QP is not online.

通过在Windows群集的日志中搜索这些关键字,可以帮助你迅速地找到isalive检查失败的时间点。

Windows Server 2008群集的日志需要通过运行以下命令行来产生:

cluster log /g

要注意Windows群集日志的大小是有限制的,它会不断地冲刷掉最老的信息。因此一旦发生故障转移,应当尽快地收集Windows群集日志.

2)  SQL Server的错误日志。

SQL Server的错误日志有助于判断为什么isalive会失败。打开SQL Server资源发生故障转移的时间点之前的那个ERRORLOG,到该文件的最后查找有没有如下这条信息:

SQL Server is terminating inresponse to a 'stop' request from Service Control Manager. This is aninformational message only. No user action is required.

如果没有这条信息,那说明SQLServer是被不正常关闭的,有可能是整个进程崩溃或者是被其他进程kill掉的。

如果看到这条信息,那说明SQLServer是因为接收到来自Windows群集的命令才停止的。一般来说,这是因为isalive检查失败导致的。请再去查看这条信息之前,在发生故障转移的时间点附近,SQL Server的ERRORLOG里有没有记录任何与性能问题、连接或者认证失败有关系的信息。这些都会帮助您进一步追踪SQL Server群集发生故障转移的原因。

3)  Windows事务日志。

Windows事务日志主要是用来检查节点是否存在I/O系统或者网络层的异常。I/O系统和网络层的异常都可能导致SQLServer群集的意外故障转移。

4)  “SQLDIAG”的扩展事件(extended events)日志

在以前版本的SQLServer中,如果resource DLL产生了任何的错误或者警告信息,这些信息会被记录到Windows的事件日志中去。在SQL Server 2012中,这些信息除了会被记录到Windows事件日志,还会被写入到名为“SQLDIAG”的扩展事件(extendedevents)日志文件中去,而且内容更为丰富。

每隔(HealthCheckTimeout/3)的时间(最小5秒),sp_server_diagnostics会获得SQL Server的诊断信息。这些信息也会被记录在SQLDIAG扩展事件日志文件里。由于默认设置HealthCheckTimeout为60秒,所以理论上SQLDIAG中每20秒就会有sp_server_diagnostics的信息被记录下来。但在实际的运行中,如果resource DLL发现上次sp_server_diagnostics的评估的结果都是“干净”,而本次的评估结果也是“干净”,那么本次的sp_server_diagnostics诊断信息就会被跳过而不被记录到SQLDIAG日志中。在记录下一次新的“干净”记录之前,最多可以跳过大约10次。如果有你爱SQLDIAG日志中发现有sp_server_diagnostics信息被跳过你没有记录下来,这意味着这段时间内评估结果一直没有改变,一直都是“干净”。如果有任何评估结果的变化,那么SQLDIAG日志中就一定有记录。

如果你把SQLServer资源的Verbose Logging属性设置为1或2的话,resource DLL会记录额外的信息到Clusterlog中,而这些信息也会同时记录到SQLDIAG日志中;另外当前的FailureConditionLevel设置也会伴随着每次sp_server_diagnostics返回的诊断信息被一并记录到SQLDIAG日志中。一旦SQL Server群集发生了意外的故障转移,你可以通过查看SQLDIAG日志文件中的内容来判断当时SQL Server发生了什么问题。

SQLDIAG扩展事件日志文件和SQLServer的错误日志一样都存放在实例的LOG文件夹中。文件名是:

<节点名>_<实例名>_SQLDIAG_<序号>_<创建时间>.xel

默认设置下,每个SQLDIAG日志文件的大小是100MB。一旦100MB被写满,或者SQL Server重启,就会产生新的文件。SQLServer最多保留10个文件,一旦10个文件写满了,最早的文件就会回收掉,然后SQL Server就可以继续创建新的文件写入信息。

你可以通过运行ALTERSERVER CONFIGURATION SET DIAGNOSTICS LOG语句来控制是否将对sp_server_diagnostics 捕获的诊断数据写入SQLDIAG日志,或者设置SQLDIAG日志的文件大小,存放位置和保留文件数量。

你可能会注意到,SQLServer 2012的LOG目录下新增了3类扩展事件日志文件,除了SQLDIAG文件外,还有:

1.  AlwaysOn扩展事件日志文件。

2.  System Health扩展事件日志文件。

我们会在第三章中再提到这两个文件。