SQL Server AlwaysON从入门到进阶(6)——分析和部署AlwaysOn Availability Group
前言:
本节是整个系列的重点文章,到现在,读者应该已经对整个高可用架构有一定的了解,知道独立的SQL Server实例和基于群集的SQL Server FCI的区别。上一节已经介绍了如何安装SQL Server Failover Cluster Instance(FCI)及其要求。
本节会深入AlwaysOn 可用组的内容,以演示部署为主线,包括如何启用只读路由和使用AlwaysOn组侦听器。并在最后演示故障转移。
在前面文章中对FCI和AlwaysOn可用组有了一定的平台要求。这里对其进行简要的回顾。
- Windows Server AD域
- DNS基础设施
- DHCP(如需)
- Windows Server Failover Cluster(WSFC)
- WSFC上的节点
下面开始深入探讨AlwaysOn及实操。
为什么使用AlwaysOn可用组?
在过去,通常会使用SQL Server FCI来实现SQL Server的高可用,这个要么基于Microsoft Cluster Services(Windows 2003)或WSFC(Windows 2008/2012)作为基础。在群集中使用下面功能使得服务器在硬件故障时能够完整迁移:
- 多网卡及TCP/IP网络用于网络冗余。
- 新的多数节点集仲裁模型 (从 Windows server 2003 SP1 开始) 移除磁盘依赖项,并增加对多站点群集的支持。
- 使用多个计算机节点以抵消核心节点硬件故障(如主板等)。
正如前面提到,唯一的弱点就是FCI依赖于共享存储。虽然有很多方式可以对其冗余,但是通常带来高开销及高配置、维护难度。另外,FCI仅仅迁移服务器硬件,并不提供单个甚至多个次要数据库副本。
当使用FCI是,WSFC对其之上的SQL Server实例提供高可用。所有的FCI节点实际上作为一个群及资源进行对外服务,当其中一个伙伴节点故障,另外一个节点会进行故障转移并重启SQL Server服务。
当使用另外一个高可用技术——镜像时,仅提供一个不可读的次要数据库副本(除非使用了快照)。同时镜像是单一数据库层面,甚至不可以进行多个库一起镜像。你可以组合FCI和镜像技术来作为一个新的高可用技术,但是明显增加了复杂度。但是镜像可以在完全独立的两个服务器,不需要共享存储,镜像的问题就是镜像数据库不可读。
还有一个高可用技术——日志传送(Log Shipping)。对于复制一个数据库进行读访问来说是一个很好的方式,但是有两个问题:次要数据库会落后于主库,并且在日志还原过程中用户要断开连接。但是它有可以提供一对多的主次数据库功能。
分析了上面几种微软自带的高可用技术之后,读者应该就明白,AlwaysOn的出现很大程度是为了弥补这些技术的不足。
什么是AlwaysOn可用组:
AlwaysOn可用组(下称AG)是将数据库的全部内容复制到一组预定义的SQL Server伙伴实例中,也称副本,用于备用或只读访问。这个功能通过创建一个包含最少两个副本和最少一个数据库的AlwaysOn可用组来实现。每个数据库仅能属于一个AG,但是副本之间可以有多个AG。每当创建一个新组并添加数据库时,会有一系列的预校验操作。如下图:(注意,某些图是作者原图,在后续部署过程中会使用本人实操的截图)
在数据库参与到AlwaysOn可用组之前,必须满足这些先决条件。完整的先决条件列表可以看:针对 AlwaysOn 可用性组的先决条件、限制和建议 (SQL Server)。然后我们就可以复制数据库到一组预定义伙伴实例中,用于读取连接。
但是,AG也有一些限制:
- 副本数量:SQL 2012中最大5个:1主4次要副本。SQL 2014中为1主8次要共9个副本。
- 同步复制的设置:最大3个,其他副本只能使用异步模式。
- 自动故障转移数量:最多2个,并且必须为同步模式。
可用组的限制可以看下图【新建可用组】向导。其中绿圈中【添加副本】选项在SQL 2012中显示灰色,因为在SQL 2012中,最多只能有5个副本。蓝圈标明了最大同步副本数量。红圈显示自动故障转移的副本数。
行版本的影响:
当启用只读的次要副本时,行版本会自动开启并对每一样添加14byte的标识。实际上所有隔离级别都透明地映射到快照隔离级别从而避免重做线程阻塞。如果没有这个,那么报表负载将受重做线程干扰。
主副本的行版本数据的添加依赖于主库上的快照隔离级别或已提交读快照隔离级别的设置。组中的库如果使用了行版本控制,那么主副本上的也会有这方面的开销(也就是比如组中多个库只有一个库使用了行版本存储,那么整个副本都会受到影响)。
通过查询“sys.dm_db_index_physical_stats”这个DMV中的“max_record_size_in_bytes”列,就可以看到这样的开销。下表描述了基于磁盘的表(非SQL 2014引入的内存表)不同设置下,可读副本数据库的版本控制行为:
可读辅助副本? | 启用了快照隔离或 RCSI 级别隔离? | 主数据库 | 辅助数据库 |
---|---|---|---|
否 | 否 | 无行版本或 14 个字节的系统开销 | 无行版本或 14 个字节的系统开销 |
否 | 是 | 行版本和 14 个字节的系统开销 | 无行版本但有 14 个字节的系统开销 |
是 | 否 | 无行版本但有 14 个字节的系统开销 | 行版本和 14 个字节的系统开销 |
是 | 是 | 行版本和 14 个字节的系统开销 | 行版本和 14 个字节的系统开销 |
详细内容可以参考:活动次要副本:可读次要副本(AlwaysOn 可用性组)
缺少统计信息的影响:
任何可读次要副本数据库都会遇到缺少统计信息引起只读负载相关的问题。所有在主库上创建或更新的统计信息都会同步并驻留到次要数据库中。所有运行在次要数据库的负载会产生临时统计信息并存储在TempDB中。这样会使得TempDB有潜在压力。这也是对TempDB要细心监控的原因之一。更多的信息可以看官方文档:活动次要副本:可读次要副本(AlwaysOn 可用性组)
优点:
尽管有所限制,AlwaysOn还是提供了一个新层次的高可用功能:
- 没有共享存储:每个服务器\实例都使用本地存储,并且移除了共享存储的单点故障风险。
- AlwaysOn侦听器服务用于接受集中请求到HA数据库组。
- 多个可用可用数据库取代了传统的一主一备(往往是不可读)。
- 更合理的Failover功能。
- 在副本层面挂起数据移动。
- 支持多IP子网。
- 可以把备份负载分摊到次要数据库。
通过把备份操作运行在只读副本数,可以降低主副本的系统压力,特别是I/O压力。多个次要副本同时可以提供DR和报表服务,当然也引入了费用的问题。其中一个需要注意的问题是AlwaysOn依旧使用数据库镜像端点作为实例间的通讯。所以和镜像一样,需要使用Windows身份验证或者证书来作为访问。所以当你需要多个AlwaysOn可用组的时候,你要记得共享相同的镜像端点。
现在可以创建一个高可用的侦听器服务,用于接受传入到可用组的请求连接。侦听器包含一个唯一虚拟IP地址和一个唯一虚拟网络名。这是目前位置数据库高可用组中最明显的变动。
通过提供一个到可用组的集中的访问点 ,客户可以减轻在数据库故障转移过程中连接字符串配置方面的问题。可以通过只读路由配置AlwaysOn组的副本,允许次要副本的数据库支持只读请求,从而移除在主副本中的并发问题。
通过AlwaysOn,你还可以选择传统的同步后者异步模式(和数据库镜像一样),同步提交模式会在主库事务传输到次要数据库并把事务恢复到次要数据库之后,主库事务才提交。对于异步提交模式,如果主次两副本的库之间的会话被打断,可能导致次要数据库的事务丢失(也就是数据丢失)。同时,异步副本仅支持手动故障转移,而同步模式支持自动或手动故障转移。
对于侦测故障,可以使用AlwaysOn的【显示面板】和SQL Server、Windows日志。而由向导驱动的部署是最简单的方法,尽管会有很多用户交互。尽管如此,基础的AO组配置和配置依旧是相当简单。
在你开始部署AlwaysOn可用组之前,首先必须启用SQL Server实例上的这个功能,确保所有参与者都要启用。同时这些节点实例都必须已经成功加入WSFC中。如下图,可以在WSFC节点上的SQL Server配置管理器中启用:
这一步需要重启SQL Server实例。
部署可用组:
下面先在前面提到的5个节点中都安装SQL Server,注意相同版本。在启用了AlwaysOn组之后,可以开始部署了。我们使用的是独立安装SQL Server。为了速度,这里使用命令行安装SQL Server。具体详见:从命令提示符安装 SQL Server 2014
加载完安装文件之后,在cmd命令中,切换当前盘符到安装文件所在的盘,本例是D盘。然后输入以下命令执行即可,注意要有足够的权限。安装之后需要检查一下是否合符条件,当然要是觉得麻烦也可以用图形化安装,只是交互操作略多。
如果用图形化界面安装请勾选上图部分
另外,为了后续的批量操作,也先把所有服务器添加到注册服务器中,注意关闭防火墙:
然后把SQL Server配置管理器中的AlwaysON 可用组开启:
然后还原微软示例数据库AdventureWorks2014。然后在clusternode1的SSMS中,选择“AlwaysOn高可用性”→右键下一级文件夹的“可用性组”→【新建可用性组向导】:
第一个界面:显示了完成一次可用性组配置所需的内容。如果是第一次搭建,请先检查是否满足要求
注意:除此之外,你还需要跟相应的管理人员获取足够的账号信息、虚拟网络名和虚拟IP地址。
接下来定义一个AlwaysOn可用性组名。这个名字会成为在WSFC内创建的群集名,并且群集内必须唯一,然后选择下一步:
然后会看到下图,为了继续进行,先手工修改恢复模式然后对数据库做一次完整备份,然后刷新一下:
刷新之后就变成下图:
在【指定副本】对话框中,可以看到向导已经帮你初始化了当前的SQL Server实例。在这里可以添加副本,也必须添加1~4(SQL 2012)/8(SQL 2014)个副本。
最后配置会是下图样子,但是目前,我们先不使用自动故障转移,接下来点开【端点】选项页:
下面开始端点的配置,如果你使用默认账号安装和配置SQL Server服务,可以看到下面端点配置:另外注意默认使用的端口号是5022(跟数据库镜像使用的一样,但是可以改变)
当通过SQL Server配置管理器变更SQL Server服务帐号(比如改成localsystem),再在这个界面刷新并点下一步的时候就会出现下图的警告:
为了方便搜索引擎搜索,下面把文字贴出:
中文: “端点”选项卡列出至少一个仅使用 Windows 身份验证的端点。但是,该服务器实例可能正以某一非域帐户运行。若要使用列出的端点,请将相应的 SQL Server 服务帐户更改为域帐户。若要继续使用该非域帐户,请更改该端点以便使用证书。
是否要使用列出的端点? 英文:The Endpoints tab lists at least one endpoint that uses only Windows Authentication. However, the server instance might be running under a nondomain account. To use the listed endpoint, change the corresponding SQL Server service account to a domain account. To continue using the nondomain account, alter the endpoint to use a certificate. Do you want to use the listed endpoints? 对于这种警告,通常有两种方式:
是否要使用列出的端点? 英文:The Endpoints tab lists at least one endpoint that uses only Windows Authentication. However, the server instance might be running under a nondomain account. To use the listed endpoint, change the corresponding SQL Server service account to a domain account. To continue using the nondomain account, alter the endpoint to use a certificate. Do you want to use the listed endpoints? 对于这种警告,通常有两种方式:
- 最合理:各节点使用同一个域账号启动SQL Server,可以使用较低权限的域用户账号。
- 权宜之计:在有些情况下,账号并非随你操作,所以你可以使用类似语句授权:
- GRANT CONNECT ON endpoint::hadr_endpoint
- TO [domain\servername$]
GRANT CONNECT ON endpoint::hadr_endpoint TO [domain\servername$]
如果没有端点,你还要手动创建:
- CREATE ENDPOINT [Hadr_endpoint]
- STATE=STARTED
- AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)
- FOR DATA_MIRRORING (ROLE = ALL
- , AUTHENTICATION = WINDOWS NEGOTIATE
- , ENCRYPTION = REQUIRED ALGORITHM AES)
CREATE ENDPOINT [Hadr_endpoint] STATE=STARTED AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL) FOR DATA_MIRRORING (ROLE = ALL , AUTHENTICATION = WINDOWS NEGOTIATE , ENCRYPTION = REQUIRED ALGORITHM AES)但是基于很多原因,还是尽量使用相同的、有足够权限的域账号进行配置。关于这部分的内容可以查阅官方文档:可用性组侦听器和服务器主体名称 (SPN)
必须由域管理员在 Active Directory 中为每个可用性组侦听器名称配置服务器主体名称 (SPN),才能为到可用性组侦听器的客户端连接启用 Kerberos。 注册 SPN 时,必须使用托管可用性副本的服务器实例的服务帐户。 对于跨所有副本工作的 SPN,必须为承载可用性组的 WSFC 群集中的所有实例使用相同的服务帐户。 使用 Windows 命令行工具 setspn 配置 SPN。 例如,要为一组 SQL Server 实例上承载的名为
AG1listener.Adventure-Works.com
的可用性组配置 SPN,所有实例都应被配置为在域帐户 corp/svclogin2
下运行:
- setspn -A MSSQLSvc/AG1listener.Adventure-Works.com:1433 corp/svclogin2
setspn -A MSSQLSvc/AG1listener.Adventure-Works.com:1433 corp/svclogin2接下来是【备份首选项】,如下图:
在这里可以选择备份操作发生在什么副本中。这里我希望选择节点4作为备份用的副本,可以像上图那样把排除副本勾选。然后转到【侦听器】页。
在【侦听器】页,选择之前配置好的侦听器。如果之前没创建,可以在这里创建,但是必须是唯一的虚拟网络名,TCP端口和虚拟IP地址(如果没有使用DHCP)。然后添加静态IP。接下来选择【添加】。最后选择【下一步】。
在【选择数据同步】界面中,选择符合条件的同步模式,前面演示过,在初始化次要数据库时,需要做完整备份和日志备份。由于前面已经做了,所以这里选择【仅联接】。下面简单解释一下:
- FULL:完整,其字面解释如下图,这个选项要求完整和日志备份,并把备份还原到每个次要副本中。
- Join Only:仅联接,已经以【NORECOVERY】模式还原数据库,这个选项直接把库加入可用组中。
- Skip initial data synchronisation:跳过初始化数据同步,这个选项可以让你在完成向导之后还原数据库和把次要副本加入AlwaysON可用性组中。
然后点击下一步。在【验证】对话框中会看到类似下图样子:
在没有报错的情况下,点击下一步并完成创建AlwaysON可用性组的配置:
完成之后可以查看结果,如无问题可以点击关闭,配置完成之后可以看到下图样子:
到目前为止,AlwaysON组已经成功创建。检查WSFC的配置,可以看到一个新的群集角色和资源分配。这里的AlwaysON群集角色表名,有一个AlwaysON组和一个已群集的AlwaysON资源,使用的是在部署向导中定义的名字。对于侦听器,我们分配了一个已群集的虚拟网络名和虚拟IP地址。需要注意的是截至到SQL 2014为止,AlwaysON都要求所有参与节点基于同一个群集,因为如果不在同一个群集,那么在发生故障转移的时候,又怎么转移群集资源呢?
注意:不要尝试去手动修改组的首选所有者或资源的可能所有者列表。任何这种修改都是徒劳无功的,因为这些在故障转移过程中,依赖于副本配置,会动态变更AlwaysON组的群集配置。
如果想查询当前AlwaysON组的主副本,可以使用下面的PowerShell命令实现:
- get-clusterresource -cluster "WindowsClusterName" | where-object{$_.ResourceType -ilike "SQL Server Availability Group"} | ft
get-clusterresource -cluster "WindowsClusterName" | where-object{$_.ResourceType -ilike "SQL Server Availability Group"} | ft注意替换上面的WindowsClusterName。
在完成之后,我们可以使用SSMS的界面进行手动故障转移,或者使用下面的脚本进行手动故障转移:
- ALTER AVAILABILITY GROUP [YourAG] FAILOVER
ALTER AVAILABILITY GROUP [YourAG] FAILOVER
配置只读路由:
在创建完带有侦听器的AlwaysON可用性组之后,可以配置只读路由以便更好地管理只读请求。在把客户端的意向只读请求重定位之前,必须先创建一个侦听器。然后配置只读路由列表用于访问AlwaysON副本。在上面的部署过程中已经创建了侦听器,所以现在可以开始配置只读路由。下面的T-SQL代码是用于在本机中配置,第一个代码块配置了一个次要角色用于可能被用来做只读路由的各个副本之用。替换代码中红色部分,这些是SQL 实例名的路由URL,注意不是镜像端点URL或者侦听器URL:
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE1\INST1'
WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE1\INST1'
WITH
(SECONDARY_ROLE (
READ_ONLY_ROUTING_URL
=
N'TCP://stokecsclnode1.stokecs2.co.uk:58001'
));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE2\INST1'
WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE2\INST1'
WITH
(SECONDARY_ROLE (
READ_ONLY_ROUTING_URL
=
N'TCP://stokecsclnode2.stokecs2.co.uk:58001'
));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE3\INST1'
WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE3\INST1'
WITH
(SECONDARY_ROLE (
READ_ONLY_ROUTING_URL
=
N'TCP://stokecsclnode3.stokecs2.co.uk:58001'
));
比如我本机环境改成:
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE1' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE1' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE1.george.com:1433'));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE2' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE2' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE2.george.com:1433'));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE3' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE3' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE3.george.com:1433'));
ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE1' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE1' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE1.george.com:1433')); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE2' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE2' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE2.george.com:1433')); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE3' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE3' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'TCP://CLUSTERNODE3.george.com:1433'));
下一步是指定在每个副本在作为主角色的时候路由首选项:
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE1\INST1'
WITH (PRIMARY_ROLE (
READ_ONLY_ROUTING_LIST
= (
'STOKECSCLNODE3\INST1', 'STOKECSCLNODE2\INST1', 'STOKECSCLNODE1\INST1'
)));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE2\INST1'
WITH (PRIMARY_ROLE (
READ_ONLY_ROUTING_LIST
= (
'STOKECSCLNODE3\INST1', 'STOKECSCLNODE1\INST1', 'STOKECSCLNODE2\INST1'
)));
ALTER AVAILABILITY GROUP
[STOKEAG_1]
MODIFY REPLICA ON
N'STOKECSCLNODE3\INST1'
WITH (PRIMARY_ROLE (
READ_ONLY_ROUTING_LIST
= (
'STOKECSCLNODE2\INST1', 'STOKECSCLNODE1\INST1', 'STOKECSCLNODE3\INST1'
)));
本机改成:
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE1' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE3', 'CLUSTERNODE2', 'CLUSTERNODE1')));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE2' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE3', 'CLUSTERNODE1', 'CLUSTERNODE2')));
- ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON
- N'CLUSTERNODE3' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE2', 'CLUSTERNODE1', 'CLUSTERNODE3')));
ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE1' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE3', 'CLUSTERNODE2', 'CLUSTERNODE1'))); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE2' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE3', 'CLUSTERNODE1', 'CLUSTERNODE2'))); ALTER AVAILABILITY GROUP GeorgeAG MODIFY REPLICA ON N'CLUSTERNODE3' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST = ('CLUSTERNODE2', 'CLUSTERNODE1', 'CLUSTERNODE3')));
最后一段代码配置每个指定的副本的主角色,包括你想分摊负载到read intent所需要连接的副本。通常需要配置所有的副本,但是也并不是强制的。如果指定了所有副本,理想情况下主副本应该作为路由列表的最后一个连接。术语“READ_ONLY_ROUTING_LIST”是从左到右枚举,优先级也是从左到右。
现在只读路由列表已经配置完成,可以通过侦听器测试。主副本是节点1,然后使用一个SQLCMD并带有意向只读去查询,可以看到当前实例名是节点三。
只读路由配置看上去跟之前会有点混乱。实际上,一旦你确定需要的副本,那么这个脚本是很容易配置的。但是要注意的是,只读URL是数据库引擎本身的URL。不是数据库镜像端口URL或侦听器URL。
挂起数据移动:
这个功能需求是非常常见的,AlwaysON组提供在主次副本层面上对加入AlwaysON数据库进行数据移动挂起功能。在某些场景下会自动触发这 种挂起。如果在AlwaysON环境下,主副本发生故障同时又没有可用的“自动转移”的次要副本,那么次要副本会进入“Resolving(正在解析)”状态,这时候就要使用手动或者强制故障转移到一个异步同步副本中。当执行强制转移时,数据移动就会自动变成挂起,这时候要重新连接到新的异步主副本的数据库。这个在接下来的测试环节会看到。
注意:当一个异步副本被强制作为主副本时,事务会发送到新的次要异步副本。
在主副本和次要副本之间挂起数据移动会停止数据同步。但是主副本的数据库依旧联机和可用。此时繁忙数据库中的事务日志的增长就会成为隐患,所以在这种情况下要小心,哪怕配置合理。
在次要副本的数据移动挂起会使得其上面的数据库状态变成“未同步(Not Synchronising)”,并且次要数据库会变成不可用。当恢复数据移动以后在主副本的积压的日志会继续同步到次要数据库并使得次要数据库恢复可用。
小心另外一个引起数据移动挂起的情况,当可用性组从SQL 2012的副本中转移到一个高版本的副本,比如2014上时,和其他SQL Server高可用技术一样,这种过程是不可逆的。不过这种方式可以用于数据库从低版本迁移到高版本的情景。
测试故障转移场景和观察结果:
下面来测试一下我们的环境是否可用。一方面是测试搭建有没有问题,另外一方面也可以作为以后在正式环境中校验的步骤。
自动故障转移:
允许自动故障转移的前提是必须有最少两个副本,且为同步模式,同时配置了自动故障转移,否则只能使用手动故障转移。在这里,使CLUSTERNODE3作为主副本,然后把CLUSTERNODE1作为同步、自动副本。然后把CLUSTERNODE3的网卡关闭,模拟硬件故障,然后理论上会发生自动故障转移到CLUSTERNODE1中。
现在在CLUSTERNODE1中打开“故障转移群集管理器”可以看到以下截图:
然后通过Hyper-V控制台,把ClusterNode3这台虚拟机的网卡设为“未连接”,再在ClusterNode1中刷新故障转移群集管理器的界面,可以看到下图:
CLUSTERNODE1已经变成了主副本。同时群集管理器中的角色所有者也变成了CLUSTERNODE1。如果没做任何干预就能实现上图情况,那证明自动故障转移没有问题。然后我们把NODE3的网卡恢复。
手动和强制故障转移:
当主副本出现故障并切换到同步或异步副本时,会被要求确认故障转移向导过程中,必须接受数据丢失的风险。然后选择作为主副本的副本进行接收事务。但是如果失败的话怎么回滚?原理是什么?
在这个测试中,把可用性组全部设为非自动故障转移模式,然后在当前主副本(NODE1)中关闭SQLSERVR.EXE进程,模拟软件故障,此时AlwaysON会变成Resolving状态,由于这个时候没有自动故障转移的伙伴副本存在,所以这种情况下主副本的故障是灾难性的。
接下来,在Node4中,作为异步同步的副本,进行强制故障转移,在转移过程中,向导会提醒你会有潜在的数据丢失风险。
先把AlwaysON配置成以下样子:
然后在NODE1中的任务管理器中终止SQL Server进程:
终止进程之后看到主节点已经失败:
切换到NODE4,可以看到当前的可用性组的状态为“正在解析”:
在NODE4中的可用性组,右键选择故障转移,可以看到下面叹号:
下一步中有明确的数据丢失风险警告:
转移成功后,可以看到NODE4中的状态变成了“主要”:
同时,在故障转移群集管理器中可以看到所有者节点现在也变成饿了ClusterNode4:
从显示面板看,其他节点均为“未同步”状态:
最后我们可以看到次要副本的数据库是暂停状态的,也就是挂起了数据移动:
右键数据库选择“”:
在同步完毕之后,数据就变得无丢失。
在故障转移过程中群集角色资源状态:
有个值得看一下的现象,在故障转移过程中的群集角色的资源状态。当把AlwaysOn组故障转移到一个手动同步的节点时,会修改首选群集角色的所有者到这个节点上。此外在 AlwaysOn 资源上的可能所属者的列表也设置为只有该节点。比如,下面的情景。当前的AlwaysOn组的主副本活动在节点1,而主副本是同步模式并且手动故障转移。然后我们看看群集角色和AlwaysOn资源的所有者列表:
当我们把主节点failover到NODE3之后,再检查:
当AlwaysOn设置为有同步副本且自动故障转移之后,资源列表又变得不同了。这里重新设置NODE3/4两个为同步、自动故障转移,然后再次查看:
注意:这些属性都是动态管理的,所以没有必要干预。
总结:
本节延时了AlwaysON可用性组的创建、配置和使用。同时测试了故障转移的情况。这一节是本系列最重要的一节,希望能反复练习。
在翻译和实操的过程中,感觉对读者的实操能力提升并没有多大的好处,最起码对于我,所以我想在这个系列过程中插入一篇从0开始搭建整个AlwaysOn的演示文章,文章里面不打算解释过多,主要以step by step为主。