SQL Server的“高可用性”与“灾难恢复” 之四 数据库镜像

SQL Server的“高可用性”与“灾难恢复” 之四 数据库镜像

5681发表于2016-05-09

根据前面的介绍读者会发现,故障转移群集技术和日志传送技术都不是那么“完美”。故障转移群集可以让系统在遇到故障时自动恢复,但是不能提供数据冗余,以对抗数据库损坏事故。日志传送可以提供冗余的数据拷贝,但是主数据库和辅助数据库之间的时间差可能比较长,故障切换也比较麻烦。所以仅有这两种技术,还是不能满足SQLServer用户的需求。

数据库镜像功能首次出现在SQL Server 2005 SP1中。它设计的目的是试图为SQL Server提供一个具有实时性数据同步的灾难恢复技术,即能提供数据冗余备份,切换起来也比较方便。相比较故障转移群集,数据库镜像同样也能够为客户端应用提供统一的连接方式,但同时它又具备故障转移群集所没有的抵御数据损失的能力。相对日志传送,它进行灾难切换要快很多,又基本对客户端应用透明。这些优点都使得数据库镜像成为了一项兼备高可用性和灾难恢复功能的技术。现在,数据库镜像技术在企业客户环境中,使用得越来越多了。

数据库镜像的基本概念

相对前两种技术,数据库镜像技术要相对更加复杂一些。本节先介绍数据库镜像里的基本术语和角色。

数据库镜像会为目标数据库创建一个副本数据库。这两个数据库分别运行在不同的SQLServer实例上,作为“伙伴”建立一个会话(session)。通过这个对话,两个数据库互相进行通信和协作,扮演互补的角色:“主体角色”和“镜像角色”,以实现“镜像”的效果。在任何给定的时间,都是一个伙伴扮演主体角色,而另一个伙伴扮演镜像角色。扮演主体角色的数据库就是主体数据库(principaldatabase),另一个扮演镜像角色的数据库则是镜像数据库(mirror database)。每个主体数据库只能有一个镜像数据库。镜像数据库作为主体数据库的一个副本,在主体数据库发生故障、不可访问时,能迅速恢复数据库访问,提供了灾难恢复的功能。

只有使用完整恢复模式的数据库才能使用数据库镜像功能。主体数据库可以象一个普通数据库一样,执行数据库查询、修改、数据库管理操作。只有很少的操作(比如还原数据库备份)由于数据库镜像的限制而不被允许执行。而镜像数据库是一个一直处于“恢复”状态的数据库,因此是不能被直接访问的。这点和日志传送不一样。但是,你可以为镜像数据库创建一个快照,这样就可以间接地访问镜像数据库里的数据了。那些用作报表查询的应用可以通过镜像服务器的快照来获取数据,这能减轻主体服务器的工作负载。

需要特别指出,只有用户数据库才能配置数据库镜像,所有的系统数据库都不能被镜像,对于系统数据库还是需要通过备份的方式来保障安全。

运行主体数据库的SQL Server实例被称为主体服务器(principalserver),而运行镜像数据库的SQL Server被称为镜像服务器(mirrorserver)。主体服务器和镜像服务器必须是两个不同的SQL Server实例。这两个实例上可以有多个数据库镜像的会话。这两个实例可以运行在同一台计算机上,但是一般不建议这么做。因为这种配置下,一旦服务器的磁盘发生物理损坏,那么主体数据库和镜像数据库就都无法使用了,灾难恢复也就无从谈起了。

 

配置了多个会话的数据库镜像(无见证服务器)

每个数据库镜像的会话都只针对一个用户数据库,而且是独立的。例如,一个应用程序需要同时访问一个SQL服务器实例上的两个数据库,那管理员就需要配置两个镜像会话。如果其中一个数据库发生故障,它的镜像会将数据库转移到镜像服务器上,而另一个工作正常的数据库则继续在主体服务器上运行。这时对SQLServer来讲,两个数据库都能被使用。但是对应用程序来讲,它就变得无所适从,连接哪个服务器都不能正常工作。由于镜像数据库相互独立,这些数据库不能作为一个组来进行故障转移。这是数据库镜像的一个很大限制。

除了主体服务器和镜像服务器之外,数据库镜像还可以配置一个叫做“见证服务器”(witnessserver)的SQL Server实例。见证服务器不是必须的。有了见证服务器,主体数据库和镜像数据库除了保持和伙伴的会话,也会和见证服务器进行对话。见证服务器上没有数据库的副本,它只是做为一个中立的仲裁,和主体/镜像服务器建立会话,判定数据库的健康状况,并在主体数据库发生异常的时候,触发自动的故障转移,让镜像数据库和主体数据库转换角色。见证服务器必须是一个独立于主体服务器和镜像服务器的实例。多个数据库镜像伙伴(无论它们是否使用相同的主体服务器和镜像服务器)可以共用一个见证服务器。最佳情况下,见证服务器实例应该配置在一台单独的计算机上,这样见证服务器的工作不会受到主体或镜像服务器异常的干扰。如果必须将见证服务器和镜像伙伴中某个实例运行在同一台机器上的话,要确保该机器具有足够资源以减少两个实例的资源争用。

可以说,配置了见证数据库的数据库镜像兼备了高可用性和灾难恢复的功能。如果数据库镜像没有配置见证服务器,就无法实现自动的故障转移。一旦主体数据库发生异常,数据库管理员需要手动进行故障转移。

配置了一个会话的数据库镜像(有见证服务器)

主体服务器,镜像服务器和见证服务器实例上都会建有一个叫做“端点”(endpoint)的对象,每个端点都侦听在一个TCP的端口上,默认的端口是5022。主体服务器,镜像服务器和见证服务器三者就是通过建立在实例上的端点,向另两个服务器发送TCP数据包来进行“会话”。一个SQL Server实例上,无论配置有多少个数据库镜像会话,它们都只使用唯一的端点。如果这三个实例中的某两个运行在同一台机器上,要确保这两个实例上的端点侦听在不同的TCP端口上。

到这里,数据库镜像的基本概念讲得差不多了。那主体数据库和镜像数据库是如何同步数据的呢?

SQL Server数据库中任何的数据变化都会先记录到事务日志中去,然后才会真正更新数据页面。而事务日志是先保存在该数据库的日志缓存(logbuffer)里,然后将缓存中的日志块固化到磁盘上的LDF文件中去。在数据库镜像中,主体服务器在将主体数据库的日志从日志缓存固化到磁盘的同时,还会使用另一个线程来将日志块发送到镜像服务器的端点。当镜像服务器通过端点接收到日志块之后,它先将日志块放到镜像数据库的日志缓存里,然后将缓存里的日志块固化到磁盘上。一旦日志块被固化之后,镜像服务器会根据日志来对镜像数据库执行“重做”(redo),最终更新数据页面。当镜像服务器重做日志时,镜像数据库实际就是在执行日志的前滚操作。如果重做失败,则镜像服务器通过将数据库置于SUSPENDED 状态来暂停会话。数据库管理员必须找到问题的原因并解决问题才能继续会话。当主体服务器截断或收缩主体数据库的日志时,镜像服务器也将在日志的同一点收缩日志。

可以看到,数据库镜像其实就是通过发送日志来保持伙伴之间的同步。从SQLServer 2008开始,日志块在被主体服务器发送到网络之前会做压缩处理。这么做的目的是为了提升日志发送和接受的效率,降低日志块传输对网络链路和网络设备所带来的负载。对于那些异常繁忙的生产系统,这项功能不但降低了由于网络不胜负荷导致的镜像对话异常中断,也降低由于网络延迟导致的数据库镜像性能问题,可谓一举两得。

无论日志块压缩与否,主体数据库上新日志生成的速率都可能会快于日志发送的速率,有些日志记录会来不及发送,而在主服务器上暂时“积累”起来。这部分累积未发送的日志产生了一个队列,叫做发送队列(sendqueue)。发送队列不会占用主服务器上额外的存储空间或者是内存,它是存在于主体数据库的事务日志文件(LDF)上。事务日志里会有一个标记,指向所有没被发送到镜像服务器的日志记录中最早的那个。那么从这个标记开始到最新的日志为止就是“发送队列”。主体服务器就不断地从这个队列中取出最早的日志,并发送给镜像数据库。

在镜像数据库里,如果日志重做的速度如果赶不上日志在镜像端固化的速度,那么也在镜像数据库的LDF文件中等待重做的事务也会产生一个队列,叫做重做队列(redo queue)。和发送队列类似,重做队列也不使用额外的存储空间和内存。它仅是使用一个标记,指向镜像数据库的事务日志文件中最早的那个还未重做的日志。镜像服务器从这个标记开始按顺序重做日志,更新数据。重做队列中等待的未重做日志数量决定了故障转移到镜像数据库所要花费的时间。

通过上面的介绍可以发现,数据库镜像技术和日志传送一样,其同步的信息也是日志记录,而不是数据操作命令。它们不同的是,日志传送是通过数据库日志备份和恢复。而数据库镜像更“直接”,它能够直接读取和标记日志文件里的日志记录。所以镜像技术的实时性会更好。

数据库镜像操作模式

那数据库镜像能做到多“实时”呢?它能否保证镜像数据库完全与主体数据库同步呢?这取决于会话的运行模式。数据库镜像有3种操作模式:高可用、高保护和高性能。使用哪一种模式取决于两点:

1. 数据库镜像的“事务安全性”设置

2. 是否有见证服务器。

下面的表(2-3)列出了三种模式及它们之间的区别。

操作模式

事务安全

传输模式

见证服务器

故障切换类型

高可用

Full

同步

自动或手动切换

高保护

Full

同步

没有

只能手动切换

高性能

Off

异步

无需配置

只能强制切换

表2-3数据库镜像操作模式

在对每个操作模式做详细介绍之前,先来了解下“事务安全性”和“传输模式”。

事务安全性是一个数据库镜像的设置选项。如果把它设置为Full的话,数据库镜像就处于“同步”传输模式。如果把该选项设置为off的话,数据库镜像就处于“异步”传输模式。

在SQL Server Management Studio中,如果你打开一个已经配置镜像的数据库的属性,在”OperatingMode”这个区域你就能看到数据库镜像当前的事务安全性设置,并根据你的需求进行更改。

查看数据库镜像的事务安全性设置

你也可以使用TSQL语句修改事务安全性设置。以下TSQL语句会将事务安全性设置为FULL:

ALTERDATABASE [<dbname>] SET SAFETY FULL;

同步传输模式和异步传输模式的区别在哪里呢?

同步传送模式下,数据库镜像是这样处理事务的:

·        从客户端收到事务请求时,主体服务器将事务的日志写入事务日志中。

·        主体服务器将事务写入数据库中,同时将日志发送到镜像服务器。这时主体服务器不是提交或回滚事务,而是等待镜像服务器完成第三步。

·        镜像服务器将日志固化到磁盘,并向主体服务器返回确认。

·        主服务器收到来自镜像服务器的确认后,结束事务操作,并向客户端发送事务完成的确认消息。

用这样的方法,镜像服务器那里没有做完,主体服务器就不会结束事务。同步传送模式通过上述的过程来保证数据在主体数据库和镜像数据库上是始终保持完全同步的。所有被提交的事务都保证会被写入镜像服务器的磁盘上。这样,事务被认为是“安全”地在两个伙伴间传输,不会有两边数据不同步的现象。但是,同步传送模式会给主体服务器上事务的提交带来额外的延迟,即使延迟可能非常微小。所以数据安全是以牺牲一定的性能来达到的。为了尽量减小延迟,你需要给伙伴服务器之间配备高速可靠的网络,同时要确保伙伴服务器拥有良好的磁盘性能。一台I/O表现不佳的镜像服务器会因为日志固化的缓慢而拖累主体服务器的性能。一般情况下,推荐伙伴服务器具有相同的硬件配置。这既是为了保障较小的延迟,也是为了确保无论那台机器扮演主体服务器都会有相同的性能表现。

异步传送模式下,主体数据库向镜像服务器发送日志之后,不会等待镜像服务器的确认,而是直接向客户端发送事务完成的确认消息。主体数据库上提交事务不需要等待镜像服务器将日志写入磁盘。因此,主体数据库和镜像数据库可能不是完全同步的。镜像服务器会尽可能的“追赶”主体服务器,想与之保持同步。但是由于网络、负载等因素的影响,镜像数据库还是有可能在某种程度上滞后于主体数据库。尽管这两个数据库之间的同步差距通常很小,但一旦主体数据库突然出了问题,在镜像数据库上可能会有一部分数据丢失。所以这种方法性能好,但是不能完全保证数据同步。

了解了事务安全性和传输模式后,你很容易就能理解数据库镜像的每种操作模式。

1. 高可用操作模式

高可用模式要求数据库镜像的安全性设置必须设置为“完整”,因此日志传输模式是“同步”模式,这样保证了在主体数据库提交的事务必定在镜像数据库端也提交了。除此之外,必须配置见证服务器,能保证在主体数据库发生异常时自动触发故障转移,这是“高可用操作模式”命名的由来。

发生自动故障转移的场景是:见证服务器和镜像服务器保持会话,而主体服务器由于发生系统故障,中断了与镜像服务器和见证服务器的会话。这种情况下,镜像服务器会将镜像数据库的角色转换成“主体”角色。除了由见证服务器触发的自动故障转移,数据库管理员也可以执行手动故障转移。

高可用操作模式适用于主体服务器和镜像服务器之间具有高速且可靠的网络连接的环境,并且用户需要系统有自动故障转移的功能。需要注意的是,如果系统有多个数据库都配置了镜像,而应用程序需要同时访问到所有这些数据库才能正常运行,那其中一个数据库发生自动故障转移并不能触发其他镜像数据库的自动转移。这时这些数据库可能会分别运行在不同的SQL实例上,从而可导致整个应用程序不能同时找到所有数据库,最终无法使用。由于数据库镜像不能实现多个数据库一同转移,高可用模式只保证了数据库层面的可用,而不能保证应用层面的一定可用。这是数据库镜像技术的限制之一。

2. 高保护操作模式

高保护操作模式要求数据库镜像的安全性设置必须设置为“完整”,但数据库镜像没有配置见证服务器。因为使用的是”完整”事务安全性,所以主体数据库和镜像数据库的是日志是保持同步的。由于没有见证服务器,没有一个仲裁的角色来判断哪个数据库出现了问题。所以一旦主体服务器无法继续工作,数据库管理员需要手动操作才能切换数据库的角色。当主体数据库和镜像数据库保持着会话且两边数据库已同步时,数据库管理员可以执行手动故障转移。如果镜像服务器实例出现故障,则主体服务器实例不会受到影响,主体数据库状态会变为“断开”连接的状态,不过依旧可以被访问。如果主体服务器出问题,则镜像对话就会被挂起,但可以将主体数据强制故障转移到原始的镜像服务器。强制切换可能造成一定量的数据丢失,因为原始的主体服务器上可能还有一些日志没有来得及发送到镜像数据库上。

如果数据库管理员不想让镜像自动切换,想要手动响应和解决主体或镜像服务器上的问题,高保护操作模式会比较适合。同样,使用高保护操作模式需要一个高速可靠的网络来支持。

3. 高性能操作模式

在高性能操作模式下,事务安全性被设置为关闭(off)。这意味着镜像数据库的日志可能会滞后于主体数据库(异步传输模式)。该模式下,主体数据库不需要等待镜像服务器接受和固化日志,就可以继续响应客户端的请求,因此不会受困于镜像服务器导致的延迟。相比较另外两个模式,处于高性能操作模式下的主体数据库会有更好的性能表现。

高性能操作模式下不需要见证服务器,唯一可以使用的切换方式是强制故障转移。这意味着高性能操作模式下的角色切换永远存在着损失数据的风险。但是这种模式,适用于对于性能要求非常高,不能忍受任何延迟的数数据库环境。如果网络状况不稳定,或者镜像的两个伙伴相隔很远,或者用户可用接受一定量的数据丢失,也可以考虑使用高性能操作模式。在现实应用中,很多用户选择了这种方式。

无论是哪种操作模式,镜像数据库总是努力跟上主体数据库的步伐,尽量保持数据的同步,在主体数据库问题发生时,你可以通过或手动或自动的方式来启用镜像数据库,保障你的应用。

客户端连接重定向及超时控制

和故障转移群集不同,数据库镜像无法提供一个虚拟的服务器名给使用数据库的应用程序。也就是说,应用程序需要知道当前的主体服务器是哪一个,才能连接上正确的SQLServer获得数据服务。一旦发生数据库镜像故障转移,用户需要通过修改连接字符串,建立别名等方式来将应用重定向到新的主体服务器。这极大地影响了数据库镜像的高可用性:对于一个高可用操作模式的数据库镜像,虽然可以自动进行故障转移,但是在手动重定向应用的连接之前,实际上应用还是不工作的。

为了增强数据库镜像的高可用性,必须能够使得应用程序可以意识到镜像服务器的存在,并且能够在主体服务器不存在时,自动重定向到那个镜像服务器。为此,微软为ADO.NET和SQL Native Client这两个数据库驱动程序添加一项特性:你可以在连接字符串中指定首选的服务器,同时也可以指定故障切换后的备选数据库。那些使用ADO.NET或者SQL Native Client来连接SQL Server的应用,通过这个特性可以获得自动重定向连接的能力。

下面是一个示例的连接字符串,Data Source属性指定的是首选服务器,而 Failover Partner属性指定的是备选服务器:

"DataSource=SeverA;Failover Partner=ServerB;InitialCatalog=AdventureWorks;Integrated Security=True;"

通常情况下我们把大部分时间扮演主体角色的服务器赋给DataSource参数,把多数时间扮演镜像角色的服务器赋给Failover Partner参数。

有了failover partner参数后,应用程序连接SQLServer的行为就变得比较复杂了:

·        当应用程序尝试连接到Data Source所指定的主体服务器并且失败的话,它就会去尝试连接Failover Partner指定的镜像数据库。因此,在数据库镜像发生故障转移(自动、手动或强制)之后,应用程序始终可以凭借这两个属性找到可以提供数据库服务的服务器。

·        如果应用程序尝试连接Data Source指定的主体服务器并且成功了,那么连接字符串中的Failover Partner属性指定的服务器就会被忽略掉。此时驱动程序会从通过主体服务器获得它的故障转移伙伴的名字,把这个名字缓存在应用程序的内存中。要注意的是,这个被缓存的名字会覆盖连接字符串中的failoverpartner属性值。也就是说,即使你在连接字符串中没有指定failover partner,甚至你有意把failover partner设置为一个错误的、非镜像服务器的实例,只要应用程序第一次能成功连接到主体服务器,应用程序就能获得正确的镜像服务器名称。

无论是通过上面两个情况中哪一种,只要应用程序得到了两个伙伴的名称,驱动程序就会遵循“连接重试算法”。不论是初次与会话建立连接,还是在中断已建立连接后重新连接,当应用程序成功无法连接到当时主体服务器后,就会去尝试连接故障转移伙伴。这时又会有两种情况:

(1)    如果成功连接,那么就会读取新的主体服务器的镜像配置信息,得到新的镜像服务器名,并缓存在应用程序的内存里。

(2)    如果连接失败,那么驱动程序会继续尝试去访问Data Source中指定的首选服务器。驱动程序就会这样不断的尝试这两个服务器,直到达到了连接超时的阈值。

这就是数据库镜像的“连接重试算法”。由于连接重试算法的存在,连接一个镜像数据库的时候,计算“超时”错误的方法也和连接普通的SQL Server数据库不同。当数据库是镜像数据库的时候,你在连接字符串中指定的connectiontimeout值和非镜像数据库的connection timeout值尽管大小一样,但实际上效果是不一样的。

假定你指定connection timeout 15 秒:

第一轮:连接Data Source指定的首选服务器,超时时间为总timeout的8% 即:15*8%=1.2秒

这时候如果连接没有成功,就试图连接故障转移伙伴(无论是从缓存中的还是从failoverpartner参数中获得伙伴的名字),超时时间也是1.2秒。

第二轮:如果连接故障转移伙伴失败,这时候,客户端数据库接口再试图连接首选服务器,超时时间设为 总timeout的16% 即:15*16%=2.4秒。 如果没有成功,就再次连接故障转移伙伴,超时时间也是2.4秒。

第三轮,超时时间是总timeout时间的24%。在后续的每轮中,连接尝试的重试时间会逐渐变大。前八次连接尝试的重试时间如下:

8%, 8%, 16%, 16%, 24%, 24%, 32%, 32%

 

重试时间使用以下公式进行计算:

RetryTime = PreviousRetryTime + ( 0.08 * TotalLoginTimeout )

(PreviousRetryTime 初始值为0)

例如,如果使用默认的登录超时期限 15 秒,则 LoginTimeout = 15。在这种情况下,前三轮中分配的重试时间如下:

轮次

RetryTime 计算

每次尝试的重试时间

1

0 + (0.08 * 15)

1.2 秒

2

1.2 + (0.08 * 15)

2.4 秒

3

2.4 + (0.08 * 15)

3.6 秒

4

3.6 + (0.08 * 15)

4.8 秒

 

也就是说,对于15秒的timeout值,实际连接服务器的最大timeout值是3.6秒! 如果前面3轮连接(1.2秒,2.4秒,3.6秒)都不成功,在你还没有用尽第四轮的4.8秒时间之前(实际上此时第四轮只剩下0.4秒),15秒超时时间就到了,你的应用程序就会报超时错误。

要增加连接服务器的真实timeout值,你只能增加总的connectiontimeout值。比如,当我们将timeout设为120秒时,那么第一轮的重试时间是120*8%=9.6秒。即便如此,第一轮的尝试连接时间还是比非镜像数据库的缺省15秒timeout时间要短。假设你现有的应用本就需要较长的连接超时,那么如果你需要把数据库配置镜像的话,一定记住要把connectiontimeout增大,否则你的应用可能非常容易就得到超时错误。

对于不是ADO.NET和SQL Native Client的驱动,即使数据库是镜像数据库,在应用程序端也不会缓存故障转移伙伴的名称,同时也不支持failover partner参数,因此就必须要考虑其他的方法来实现连接重定向,比如说在应用程序的代码中加入重试和重定向的逻辑。

其实,镜像切换还有许多需要考虑的事情。举例来说,数据库镜像只能保持用户数据库中数据的同步,而系统数据库是无法配置镜像的。也就是说,登录名、SQLServer实例的配置、维护计划、作业等保存在master、msdb或 model数据库里的信息在镜像的两台服务器上并不是同步的。一旦发生故障转移,即使数据库依旧可用,应用程序可能会因为各种原因无法正常工作,比如:

·        应用程序使用的登录名在新的主体服务器上不存在

·        新的主体服务器上虽然已经有同名的登录名,但是该登录名的SID和原始主体服务器上的登录名不相同。于是在故障转移后形成了孤立用户。这时可以用sp_change_users_login存储过程来解决问题。

·        SQL作业会使用一些SQL Server以外的资源(例如一些文件),但是这些资源在两台服务器上存放的路径不同。

·        两台服务器的配置不同,新的主体服务器由于不够优化而导致性能极差。

凡此种种,都是你可能面临的问题。如何在主体数据库和镜像数据库间同步用户数据库以外的信息,是一个必须考虑的问题。

数据库镜像的监控和故障排查

要了解数据库镜像的运行状态,对发生的问题进行故障排查,我们可以收集以下数据。

1.  SQL Server的ERRORLOG。

在主体服务器,镜像服务器和见证服务器上,ERRORLOG中都会记录每个镜像数据库所处的状态,每个数据库当时处于什么角色,以及服务器彼此间的连通状况。

比如,这段日志表明镜像的端点已经成功监听在了端口5022上。

2006-03-29 00:34:27.87spid12s Server is listening on [ 'any' <ipv4> 5022].
2006-03-29 00:34:27.87 spid12s The Database Mirroring protocol transport is nowlistening for connections.

下面这段日志说明数据库处于镜像角色

Database mirroring isactive with database 'xxx' as the mirror copy. Thisis an informational message only. No user action is required.

如果发生连接故障的话,ERRORLOG中会记录镜像数据库的状态变化,以及连接问题的错误代码。这些错误代码对我们分析和定位连接会非常有用。这里举一些例子:

(1)  由于发生了自动故障转移,数据库转换了角色。

镜像服务器的ERRORLOG:

The mirrored database"XXX" is changing roles from "MIRROR" to"PRINCIPAL" due to Auto Failover.

主体服务器的ERRORLOG:

The mirrored database"XXX" is changing roles from "PRINCIPAL" to"MIRROR" due to Role Synchronization.

(2)  伙伴服务器之间发生网络连接错误。

2011-06-05 07:51:10.73 spid40s    Error: 1474, Severity: 16, State: 1.

2011-06-05 07:51:10.73 spid40s    Database mirroring connection error 4 'An error occurred while receivingdata: '10054(An existing connection was forcibly closed by the remote host.)'.'for 'tcp://test.testdomain.com:5022'.

2011-06-05 07:51:17.27 spid40s    Error: 1474, Severity: 16, State: 1.

2011-06-05 07:51:17.27 spid40s    Database mirroring connection error 4 'An error occurred while receivingdata: '64(The specified network name is no longer available.)'.' for 'tcp://test.testdomain.com:5022'.

(3)  伙伴服务器不响应连接请求,可能是出现了严重的性能问题。

2007-10-24 23:22:22.87 spid30s Error: 1479, Severity: 16, State:2.
2007-10-24 23:22:22.87 spid30s The mirroring connection to "tcp://test.testdomain.com:5022"has timed out for database "xxx" after 30 seconds without a response.Check the service and network connections.

除此之外,ERRORLOG中当然还记录了各种SQL Server遇到的异常,这些异常可能是非常重要的参考信息,可以用来推断数据库镜像发生故障转移或者无法正常工作的原因。

2.  性能监视器。

数据库镜像在性能监视器中有一个专门的对象SQLServer:Database Mirroring。这个对象下的计数器对于了解数据库镜像运行的状态,有着非常重要的作用。

在主体数据库上,你可以检查Transaction Delay 计数器以确定数据库镜像是否影响主体服务器的性能。检查Log SendQueue KB计数器,以确定发送队列的大小。如果send queue很长的话,有可能是镜像数据库处理日志慢导致的,也可能是由于网络传输慢导致的。主体服务器的Log Bytes Sent/sec 计数器显示了每秒发送的日志量。可以计算“(Log SendQueue)/( Log Bytes Received /sec)”来估算镜像数据库需要多长时间才能追赶上主体数据库。

在镜像数据库上,LogBytes Received/sec计数器显示了每秒接收到的日志量。你可以检查Redo Queue KB计数器来确定重做队列的大小,就知道有多少日志没有被重做。如果Redo queue很大的话,这往往意味着镜像数据库存在I/O瓶颈。镜像数据库上的Redo Bytes/sec计数器显示了执行重做操作的速率。前面已经提到过,发生故障转移的时候,原始的镜像数据库需要把重做队列里的日志都重做完才能真正上线运行。我们可以通过计算“(RedoQueue)/(Redo Bytes/sec)”来估算一旦发生故障转移,需要多长时间才能完成全部重做操作。

这些计数器,配合一些系统自带的计数器(例如,物理磁盘,网络等对象下的计数器),可以很直观地定位到数据库镜像的性能瓶颈。

3.  数据库镜像监视器。

数据库镜像监视器是一个图形用户界面的工具,你可以用它来来监视镜像镜像伙伴以及镜像会话的状态,利用这些信息你可以评估在当前状况下完成故障转移所需的时间,和潜在的数据丢失量。你也可以为一些您认为很重要的指标(如sendqueue,redo queue)配置警告阈值,一旦超过你设置的阈值就触发警告来通知数据库管理员。

 

4.  系统存储过程和系统表

可以通过运行sp_dbmmonitorresults 系统存储过程来查看当前数据库镜像的状态。你可能会感兴趣数据库镜像监视器或者sp_dbmmonitorresults是从哪里获取信息的。其实,这两者都是来自于一个MSDB数据库中的系统表dbm_monitor_data。而这个系统表的更新由以下两者完成:

(1)   当使用 SQL ServerManagement Studio 启动镜像会话时,会自动创建一个“数据库镜像监视器作业”。这个作业每分钟更新一次dbm_monitor_data系统表。如果你是使用 ALTER DATABASE database_name SET PARTNER 命令来创建镜像会话的话,这个作业就不存在了。但是你可以执行sp_dbmmonitoraddmonitoring 存储过程来手动创建这个作业。

(2)   数据库镜像监视器每30秒更新一次dbm_monitor_data系统表。

事实上这两个方法背后都是调用了sp_dbmmonitorupdate存储过程来更新信息。你可以手动运行这个存储过程来更新dbm_monitor_data。无论你使用什么方法,SQL Server会保证每两个更新的间隔不小于15秒。

sp_dbmmonitorupdate是一个非常重要的存储过程。如果你有兴趣的话,你可以去查看它的定义,你会发现这个存储过程是通过查询sys.dm_os_performance_counters这个视图来获得性能相关的数据,并且sp_dbmmonitorupdate通过将用户设置的阈值与sys.dm_os_performance_counters进行比较来确定是否并触发警告。而sys.dm_os_performance_counters中的数据和性能监视器中SQL Server:Database Mirroring下的计数器是一一对应的。

以上就是诊断数据库镜像问题时通常需要收集的信息。数据库镜像的问题主要是两类:

1. 诊断发生故障转移的原因(对于非高可用模式的镜像,就是诊断镜像停止工作的原因)。

对于这类问题,你需要收集主体服务器,镜像服务器和见证服务器(如果有的话)上的ERRORLOG。如上面所讲的,ERRORLOG里会记录什么时候镜像发生了问题,发生了什么类型的问题,以及最终的结果如何。最重要的是,你不能孤立地去分析各个ERRORLOG,而是应该将它们彼此作为参考,互相印证。举例来说,如果你在主体服务器的ERRORLOG里发现了主体服务器失去了镜像服务器的连接,你就应当去查看镜像服务器和见证服务器ERRORLOG中相应时间点的日志,去了解当时镜像服务器和见证服务器是否能连接到主体服务器。只有了解了所有服务器彼此之间的连通状况,才能正确判断出当时是那台服务器的网络端出现了问题。

2. 性能问题。

由于只有主体服务器才能影响应用端的请求,性能问题都会体现在主题服务器端。例如主体服务器上事物提交有严重的延迟,或者是发送队列很长等等。但是这类问题的最终症结往往却不在主体服务器上,而在镜像服务器上或者是在网络上。要诊断这类问题,需要在主体服务器和镜像服务器上打开性能监视器来记录各项镜像相关的数据,以及磁盘、网络、内存、CPU相关的数据。此外数据库镜像监视器也能帮助你了解主体/镜像服务器的运行状态。通过这些数据,你可以了解镜像服务器的处理事务的效率,网络传送事务的速度,以及镜像端的磁盘负载和磁盘性能(往往是最大瓶颈)等情况。掌握了这些信息,你就可以判断出问题的源头:是否主体服务器的负载已经超出了镜像数据库的容纳范围,是否网络性能低于设计容量,等等。

小编蓝狐