SQL Server

实现 SQL Server 的高可用性

Zach Nichter

 

概览:

  • 镜像
  • 数据库快照
  • 日志传送
  • 群集
  • 复制

下载这篇文章的代码: NichterHA2007_03.exe (151KB)

高可用性是每个数据库管理员都应该理解的一个概念。它指的是系统的响应性和可访问性。有时,高可用性表示响应时间为几秒钟,而其他情况下则要求响应时间以

分数秒计。我曾咨询过一家公司,那里的 Web 服务器要求 SQL 查询的往返响应时间为几毫秒;如果响应超出该限制,则数据库系统被视为停用,Web 服务器将重新连接到下一个可用的数据库服务器。

随着用户对应用程序速度的要求越来越高,了解如何实现高可用性和快速响应时间将有助于您明智地规划依赖于数据的应用程序。

幸运的是,SQL Server™ 2005 具有多个用于提高可用性的选项,其中包括复制、群集、数据库镜像、数据库快照和数据库日志传送。我将对这些功能进行介绍并深入讲解如何确定哪些功能恰好适合于您的环境。让我们先来看一下图 1,其中介绍了 SQL Server 2005 中的可用性选项。

Figure 1 高可用性选项

技术特点 复制 数据库镜像 群集 数据库快照 日志传送
高可用性选项  
可承受高事务要求  
实时数据可用性  
数据映像为只读    
硬件配置唯一        
成本低  
提供数据恢复  
自动故障转移      
实现/管理可能较为复杂    
可能需要考虑性能问题    

定义高可用性

规划高可用性应用程序时的首要目标之一就是定义其在特定环境中的含义。对于一些组织,高可用性意味着必须要有等同于生产硬件的冗余硬件,同时要求数据和硬件的正常工作时间和可用性都能达到 99.995% 或更高。其他组织可能仅要求数据本身具有高可用性,而对生产级性能关注较少(假如故障转移是必需的)。在确定恰好适合您情况的解决方案时,定义高可用性非常重要。

另外,还需要确定可能遇到的停用类型,并指明它们对服务级协议 (SLA) 有何影响。可能对可用性产生影响的停用包括计划内、计划外停用以及性能下降。

计划内停用通常是一段安排好的维护期,将会就此预先通知系统用户。计划外停用通常是由于硬件或软件故障造成数据无法访问而导致的。性能下降也可能造成停用,它常常以最终用户的响应时间来进行衡量,通常,企业以及 IT 组织已预先以某种形式的 SLA 对此达成共识。

除了识别潜在的停用源之外,还必须确定数据的活动级别,以及数据必须始终在线还是可以有时近线或离线。还必须决定可用性选项将处于同一地理位置还是处于远程位置。在决策时可能还需要考虑预算限制。现在就让我们来看看每一个可用性选项。

数据库镜像

在深入探讨数据库镜像之前,我要首先定义术语。

主体 是存放数据库的主生产服务器,它不断地将其事务日志发送给镜像服务器和数据库。

镜像 是存放数据库备份副本的辅助服务器。镜像副本与主体数据库始终保持同步。

角色 指明了特定服务器的用途,即它是担当主体还是担当镜像。

见证方 是在主体和镜像服务器各行其职时对其进行监视的实例,并且它可以发起自动故障转移。

伙伴 可以是主体服务器也可以是镜像服务器。

在典型环境下,将在主体实例上备份主体数据库,并且将在镜像实例上对备份进行还原(请参见图 2)。一旦还原了数据库,就必须使用 SQL Server Management Studio (SMSS) 中主体数据库的属性窗口或使用 T-SQL 脚本在主体服务器上建立镜像。

Figure 2 Database mirroring architecture

Figure 2** Database mirroring architecture **(单击该图像获得较大视图)

在配置了镜像并建立好镜像会话后,主体和镜像数据库即会进行同步。主体数据库随后会发送自上次在镜像上应用备份以来所发生事件的事务日志。镜像将接收该日志并尝试尽快应用它。如果使用的是 SQL Server 2005 Enterprise Edition,则此进程为多线程,否则便是单线程操作。这些日志一经应用于镜像,数据库即被视为已同步并且将继续保持同步直到镜像会话中断。

在客户端执行新事务时,主体服务器会针对主体数据库执行这些事务,与此同时,还会将事务日志记录从主体数据库传送到镜像数据库的重做日志或日志队列,在此会选取日志记录并将其应用到镜像数据库。在镜像数据库上应用并提交事务后,即会向主体发送回复,宣布已在镜像上提交了事务。主体在从镜像那里收到确认之前,将不会确认任何可能进入系统的新事务。

在发生故障的情况下,镜像可以发起自动故障转移,而见证方会通过判断主体数据库是否可用来支持该过程。发生故障后,必须先解决镜像伙伴上目前所出现的问题,然后它才能再次成为主体伙伴。解决了镜像伙伴上出现的问题后,便开始退回到镜像伙伴服务器,并且数据库会再次进行同步。一旦它们进入同步状态,便可再次开始镜像会话。

这种特殊的镜像模式具有高度安全性,它通过开启事务安全性来提供同步事务性操作,但它不需要见证方,因为它并不利用自动故障转移,所有故障转移都是手动发起的。还有另一种提供同步事务性操作的镜像模式,即高可用性模式。该模式不仅需要开启事务安全性,还需要使用见证方在发生故障时自动进行故障转移。

镜像时可以使用的第三种也是最后一种模式为高性能。该模式需要关闭事务安全性以行使异步操作支持,进而它允许主体伙伴上的事务不必等待事务记录被写入镜像即可提交。高性能模式在配置中不需要见证方。

请注意,镜像操作要求主体和镜像上的 SQL Server 为同一种版本,但不包括见证方,其上可以是 SQL Server Express Edition。此外,主体数据库应处于完全恢复模式,这一点很重要。

ADO.NET 2.0 已与 SQL Server 2005 集成在一起,其中加入了支持数据库镜像的功能并且提供了应用程序到镜像环境的透明故障转移。这就使得 ADO.NET 应用程序在无法与主体数据库建立连接时,无需另外进行任何编码或配置即可自动进行故障转移。其配置就像在两个环境之间指定公共用户以及在连接字符串中指定故障转移伙伴一样容易。以下是 ADO.NET 连接字符串的一个示例,用于为镜像数据库环境确定故障转移伙伴:

"Provider=SQLNCLI.1;Data Source=MirrorDB;Failover Partner=SQL03;
 Initial Catalog=AdventureWorks;
Persist Security Info=True;User ID=TestUser; Password=TestPswd; Pooling=True;
Connect Timeout=5;Application Name=ADOMirrorTest"

根据您的应用程序和数据需求,数据库镜像对于贵公司来说可能是一个不错的选择,但是为了获得最佳性能,还有许多事情需要考虑。例如,系统的事务率有多高,数据更改量有多大?在考虑数据库镜像时,关键是要判断带宽和网速是否足以处理该数据量和事务处理率。另外,还要考虑链路的饱和度。在镜像位于另一不同地理位置的情况下,这一点尤为重要。预先监视系统对于判断是否存在防碍镜像有效工作的任何环境限制至关重要。

如果您力图压缩成本,则数据库镜像可能是一个非常不错的选择。事实上,数据库镜像体系结构不需要共享磁盘,并且无需具备高级或专门的技能便可运行该环境。而且与群集不同的是,数据库镜像不需要伙伴双方具有相同的硬件。此外,使用数据库属性窗口的镜像选项卡上已有的设置向导(请参见图 3),镜像实现起来很简单。我还建议大家阅读白皮书《Database Mirroring Best Practices and Performance Considerations》(数据库监视最佳实践与性能注意事项)以了解更多有帮助的信息,其网址为 go.microsoft.com/fwlink/?LinkId=80897。

Figure 3 Mirroring setup wizard

Figure 3** Mirroring setup wizard **(单击该图像获得较大视图)

数据库快照

数据库快照是 SQL Server 2005 Enterprise Edition 中提供的一项新技术,但它未被视为高可用性选项。数据库快照在与其他技术一起使用时应作为一种恢复手段或可行的报告选项来使用。快照只不过是数据库在特定时间点的只读视图。

快照是使用如下的 CREATE DATABASE 命令创建的:

CREATE DATABASE SnapDB_20061028_2030 ON
(NAME = SnapDB_Data, FILENAME = 
    'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\SnapDB_20061028_2030.snp')
AS SNAPSHOT OF SnapDB;
GO

创建数据库快照后,它会使用称为稀疏文件的一个或多个文件,而不是像典型数据库那样使用数据文件。这些稀疏文件实质上是虚拟存放所,最初并没有任何数据。仅当在源数据库中更改或删除了数据时,才会使用它们来存放该数据。数据以一次一个数据页的方式写入这些稀疏文件,并且实际的数据库快照仅显示自取得快照以来更改过的数据。其余的数据来自源数据库的数据页。

数据库快照文件是以取得快照时的数据库大小进行分配的。所分配的大小并未表明它们实际存放了多少数据。要获取该信息,请运行如下的 T-SQL 语句:

SELECT *
FROM fn_virtualfilestats(DB_ID(N'SnapDB_20061028_
    2030'), 1);
GO

鉴于数据在稀疏文件和源数据库中的存储方式,在访问数据库快照时,会同时对原始数据库数据文件中的数据页和快照的稀疏文件中的数据页进行检索。由于需要共享数据页,快照只能与从中取得快照的源数据库一起呆在相应的服务器上。由于此体系结构并没有减轻源数据库上的 I/O,而且快照体现不出数据库的真正状态,因此快照不是一种行之有效的报告选项。

考虑一个数据库镜像与快照结合使用的方案。这就使得报告数据、镜像以及快照数据库得以从主体数据库中物理分离出来。数据库快照使用 SQL Server 代理和一个定期提供刷新快照的自定义脚本进行了计划安排。图 4 中的示例脚本显示了用于实现此目的的存储过程。它设计用来在作业内部对所处环境中特定数据库的快照创建和丢弃进行管理。这就为一个可接受的报告解决方案留下了余地,因为报告数据将会与生产数据隔离开来。

Figure 4 用于对快照进行计划安排的存储过程

use msdb;
GO
set nocount on
GO

CREATE PROCEDURE usp_snaprefresh 
     @database    sysname = NULL    --name of the database to snapshot
    ,@keepsnap    int        = 24   --# of hours to keep a snapshot 
                                    --after it was created 
                                    --use a value of '0' to keep all
                                    --existing snapshots
    ,@fileloc    sysname            --location for snapshot
        = 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\'    
AS

DECLARE 
     @dt            datetime        ,@cnt          int
    ,@databaseid    int             ,@snap         sysname
    ,@sql           nvarchar(1000)  ,@yy           varchar(4)
    ,@mm            varchar(2)      ,@dd           varchar(2)
    ,@h             varchar(2)      ,@m            varchar(2)
    ,@lname         sysname         ,@pname        sysname
    ,@file          sysname         ,@pos1         int
    ,@pos2          int

-- initialize variables
SELECT 
     @dt = getdate()
    ,@cnt = 0, @pos1 = 0, @pos2 = 0
    ,@databaseid = db_id(@database)

-- check if valid database was provided
IF @databaseid IS NULL
BEGIN
    RAISERROR ('Missing database name. Rerun the procedure specifying a
       valid database name.',16,1)
    RETURN (0) 
END

--determine if snapshots should be kept
IF @keepsnap <> 0
BEGIN
    -- determine if other snapshots exist for this server older than @
    -- keepsnap value hrs
    SELECT ROW_NUMBER() OVER(ORDER BY name DESC) AS [RowNum], 
        name INTO #t1 
    FROM master.sys.databases 
    WHERE source_database_id = @databaseid
        AND create_date < dateadd(hh,-(@keepsnap),getdate())

    IF (SELECT max(RowNum) FROM #t1 where name is not null) > 0
    BEGIN
        WHILE @cnt <= (SELECT max(RowNum) FROM #t1)
        BEGIN
            SELECT @snap = name FROM #t1 WHERE RowNum = @cnt

            PRINT 'Dropping snapshot ''' + @snap + ''''

            SET @sql = 'DROP DATABASE ' + @snap

            EXEC(@sql)
            SELECT @cnt = @cnt + 1
        END
    END
END

-- break apart point in time date time information for file name
SELECT @yy = convert(varchar(4),year(@dt)),@mm = convert(varchar(2),
   month(@dt))
    ,@dd = convert(varchar(2), day(@dt)),@h = convert(varchar(2),
         datepart(hh,@dt)) 
    ,@m = convert(varchar(2), datepart(mi,@dt))

-- piece together the database snapshot name and the file name
SELECT @file = @database + '_' + @yy + @mm + @dd + '_' + @h + @m

-- identify logical file name of primary data file
SET @sql = 'SELECT name INTO tempdb..t1
FROM ' + @database + '.sys.database_files 
WHERE file_id = 1'

EXEC(@sql)

--setting logical filename for the snap
SELECT @lname = name FROM tempdb..t1

-- making sure the file location ends with '\'
IF substring(@fileloc, len(@fileloc), 1) <> '\'
BEGIN
    SET @fileloc = @fileloc + '\'
END

-- build sql statement to be run
SET @sql = N'CREATE DATABASE ' + @file + ' ON
(NAME = ' + @lname + ', FILENAME = ''' + @fileloc + @file + '.snp'')
AS SNAPSHOT OF ' + @database

EXEC(@sql)

-- cleanup
DROP TABLE tempdb..t1;
GO

不过,请记住,之所以认为数据库快照是临时性的,是因为快照无法备份并且没有源数据库便不能存在。如果稀疏文件用尽了空间,快照将被视为已毁坏而必须丢弃。

此外,若使用数据库快照,在对源数据库执行数据修改操作期间,系统性能可能会下降,因为对于取自源数据库数据文件的每个快照,均会将数据页写入稀疏文件。这就使得写入次数按数据库所具有的快照数成倍增长。

读取权限由源数据库在快照点定义,并且无法更改。快照必须与源数据库驻留在同一个实例中,因为它们共享数据页以及同一个缓冲区高速缓存。

仅当镜像也在使用时,才应考虑使用快照作为报告解决方案;否则,您的环境不会有性能上的改进。数据库快照可能是在系统上运行可疑操作之前保留数据的最快方式。可使数据库重新回到快照状态,也可从快照中取出数据以替代源数据库中的数据。

您将需要为快照数据库确定一个命名标准。我使用的标准是 originaldatabasename_date_time.snp。它首先指定了源数据库,然后是取得快照的日期和时间(采用 24 小时格式)。

日志传送

日志传送是一个有限的高可用性选项,它可利用备份和恢复建立一个成本非常低的解决方案。日志传送定期利用事务日志备份来使辅助数据库保持最新。

SQL Server 2005 中的日志传送使用向导来完成设置、计划安排、初始化和监视的整个过程(请参见图 5)。此过程很简单,几分钟之内即可完成。

Figure 5 Log shipping setup wizard

Figure 5** Log shipping setup wizard **(单击该图像获得较大视图)

确定了主数据库之后,会创建一个时间表并为备份文件确定文件时效。接下来,必须为备份文件建立文件共享。设置了文件共享之后,需要建立辅助数据库文件位置,并且必须通过完成主数据库的还原来初始化该数据库。最后,必须为备份文件副本以及事务日志备份恢复连同每一步所需的任何警报和延迟设置时间表。

设置完成后,日志传送即会按预定时间将数据库的事务日志备份到某个共享的网络位置。将文件发送到共享位置后,会按照设定的时间表将备份应用到辅助数据库。

日志传送简单方便,因此它在许多情况下都工作良好。要实现成本较低且能够处理高事务系统的高可用性,这是一个不错的选择。日志传送中采用的辅助数据库可以在只读模式下使用,从而为报告数据库提供了便利。日志传送所需的开销最低,但在处理故障的情况下,警报策略对它而言确实是必不可少的。

如果您正在考虑在您的环境中使用日志传送,那么您是考虑到了这样几点,即它设置和管理起来简单易行而且只需很少或根本不需要专门技能。然而,日志传送不是一种实时的高可用性解决方案,尽管可以将其与数据库镜像结合起来以实现此目的。它会受到时间表以及诸如备份、文件复制和还原等操作的限制。它还需要手动进行故障转移。出于上述原因,日志传送只能为那类对时间要求不太敏感的环境提供一种简单的解决方案。

SQL Server 群集

服务器群集工作在 OS 级别,其中涉及到重复的硬件以及群集要访问的共享磁盘资源。群集功能也许对最终用户的干扰最少,但它也可能是最为昂贵的。它所需的硬件数量至少是运行非群集实例所需硬件数量的两倍。

群集主题涉猎范围很广,因而我在此将不对各种细节进行探究,而只是给出一般性概述。群集需要两个或多个服务器,它们全都必须装有相同版本的 Windows® 2000 Advanced 或 Datacenter edition,或者 Windows Server® 2003 Enterprise 或 Datacenter edition。它还需要安装 Microsoft® Cluster Services (MSCS),用于处理服务器之间共享资源的所有权并管理 IP 地址、共享磁盘和网络名。群集还需要共享的磁盘资源,其形式通常为存储区域网络 (SAN) 或 SCSI 连接存储器。

SQL Server 实例也被视为一种资源,标准版和企业版的 SQL Server 2005 均可以安装在群集配置中。有关这两版 SQL Server 2005 均支持的功能列表,请参阅“SQL Server 2005 的功能比较图表”(英文)(microsoft.com/sql/prodinfo/features/compare-features.mspx)。

在群集上建立了资源后,群集的辅助节点即会通过群集两节点间的专用网络上所建立的检测信号与群集主节点保持定期通信。检测信号是按固定时间间隔取得的检查点,用以确定主节点是否发生故障。

倘若主节点发生故障,资源将被移至辅助节点,同时保持逻辑服务器原来的状态。这使得客户端在交互时只需稍事停顿就可以继续工作。整个故障转移过程所需时间可能不等,少则不超过 5 秒,而在某些情况下则需要 30 秒或更多的时间,具体取决于群集中所包括的硬件、软件和联网组件。

群集可能是一种昂贵而又复杂的技术,需具备专门技能方可解决系统上发生的故障;不过,它可为选用任何自动故障转移的最终用户提供最平稳的故障转移。每个应用程序各有不同,有些可能无法识别群集或与之不兼容,在最坏的情况下需要应用程序重新连接。

复制

SQL Server 2005 复制也可用于高可用性体系结构。它提供了四种类型的复制:快照、事务、对等以及合并。对等实际上就是某种形式的事务性复制,所以我在此将不对其进行讨论。

使用复制,您可以选择采用辅助站点和数据库来实现高可用性,它们在功能上与主数据库完全一样。可以通过合并复制来达到此目的,这种复制从主数据库和辅助数据库中取得事务,然后将两者之中的更改相互合并。您可能已经猜到,在此配置中需要一个冲突解决过程。

事务性复制在逻辑设计上与数据库镜像非常相似。应用到主数据库的事务将被传送给辅助数据库以确保环境保持一致。事务到达后即会将其应用到辅助数据库,随后,该数据库将等待要在系统中应用的下一个事务。

快照复制在以下方面与日志传送非常相似:它们都按预定的时间间隔运行并以批量更改方式更新辅助数据库,而非在提交事务时将每个事务应用到两个系统。两种技术的利用方式也几乎相同。

复制需要具备专业知识,这对于没有专门 DBA 的环境是一个很大的问题。复制在故障排除方面可能有些复杂,如果要将其用作高可用性选项,确实需要进行更加繁杂的设计。

复制可以适当地满足高可用性解决方案的需求。此项技术在记录级别使用事务性复制做到了数据库镜像所能做到的事情,只是不具有自动故障转移选项。假如您有足够的资源和一点创造性,为自动故障转移编写解决方案脚本应该不成问题。

与数据库镜像不同的是,源数据库和目标数据库对于客户端应用程序都可以完全访问。复制可凭借快照复制提供与日志传送相同的功能。

不过,有件事情可以考虑,复制技术已身经百战并且有详实的文档资料。尽管使用复制作为高可用性解决方案有一些缺陷而且性能也值得关注,但那充其量也与数据库镜像差不多。使用复制设计的任何高可用性解决方案都极可能有一个更为复杂的体系结构需要管理,该体系结构不一定更先进,但绝对更为棘手。此外,需要考虑的最大障碍之一是,如果数据库表结构发生变化或是您想要添加即将复制的表,则必须中断并重定义发布,才能使更改最终在两个数据库中都生效。

总结

您现在可以看到,为您的环境创建高可用性解决方案是何以需要一点创造性的。每种 SQL Server 2005 高可用性技术都有其强项和弱点,并且各自适合于不同的情况。

对于主 Web 数据库与辅助数据库在地理上分开的环境(尤其是当它们不要求辅助数据实时可用时),在高性能模式下,日志传送、快照复制,甚至于数据库镜像,都很不错。

另一方面,如果辅助数据库有实时数据方面的要求,则在主服务器上的事务率较低且两个环境站点之间的链路较快并且不饱和的情况下,事务性复制或数据库镜像可以担当此任。

还要考虑您对这些技术的惬意程度。如果您已有其中某些技术的工作经验,可能会好一些。如果您是经理而没有专门的 DBA,请尽量避开像复制那样较为复杂的技术,其中存在许多移动部件并且故障排除可能会很复杂。也可以考虑聘请一位有经验的 SQL Server 顾问帮助您设计、实现一个适合您环境的新的高可用性方案,并在可能的情况下帮助培训您的员工对其进行管理。

如果贵组织中的高可用性只要求数据在绝大部分时间可用并且对数据停用时间非常注重,则群集可能会是您的选择。

总而言之,SQL Server 2005 提供了许多实现高可用性的新选项,它们可以适应各种不同的环境。单个可用性选项就可能适合您的需要,或者,您也可以选择组合利用多种技术,但正如您现在所知道的,有各种各样的选择可供您采用。

Zach Nichter 是一位具有 10 多年经验的 SQL Server 专业人员。他承担过多种 SQL Server 支持角色,包括 DBA、团队领导、经理和顾问。目前,Zach 受雇于 Levi Strauss & Co. 担任 DBA 架构师,重点关注 SQL Server 性能、监视、体系结构以及其他战略性动议。

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.