16.1 实现 AlwaysOn 可用性组
以下通过实验说明配置 AlwaysOn 可用性组的过程。
现有环境如下:
服务器名称 | 角色 |
SQLSVR1 | WSFC 节点,默认实例 |
SQLSVR2 | WSFC 节点,默认实例 |
SQLSVR3 | WSFC 节点,默认实例 |
需要添加到 AlwaysOn 可用性组的数据库为 SQLDB01 和 SQLDB02。
16.1.1 先决条件
SQL Server 2012及后续产品才支持 AlwaysOn 可用性组,而且只有企业版才可以使用此功能。
加入 AlwaysOn 可用性组的节点计算机必须加入 WSFC (Windows Server Failover Cluster)。
由于需要使用事务日志在各个节点之间进行数据更新,因此,加入AlwaysOn可用性组的数据库必须为完整恢复模式。
类似于日志传送的数据库初始化操作,如果其他节点的实例没有初始化数据库,则配置向导允许自动对主数据库进行完整备份并将备份文件放置在共享文件夹。在这种情况下,建议其他节点计算机的实例使用域帐户启动,以访问共享文件夹。
16.1.2 启用 HADR
打开 SSCM(SQL Server 配置管理器),编辑数据库引擎实例的属性。在“AlwaysOn 高可用性”选项卡中,显示当前节点计算机已经加入的 WSFC 名称,勾选下方的“启用AlwaysOn可用性组”选项,从而允许此 SQL Server 实例在高用用性和灾难恢复(High Availability and Disaster Recovery,简称 HADR)解决方案中使用 AlwaysOn 可用性组。
必须为每个节点计算机的数据库引擎实例都启用此 HADR 选项。
16.1.3 启动向导
打开 SSMS,连接到 AlwaysOn 可用性组的主节点实例(即主要副本)。在“对象资源管理器”的左侧树状列表中展开“AlwaysOn 高用用性”,然后在“可用性组”上单击右键,在右键菜单中选择“新建可用性组向导”。
在“新建可用性组”向导的“简介”页,单击“下一步”开始配置一个可用性组。
16.1.4 配置可用性组
(1)指定名称
为可用性组指定一个名称。这个名称用来在 SSMS 的“可用性组”节点下面创建一个子节点。
(2)选择数据库
这里面将列出主节点实例中所有的用户数据库。对于完整恢复模式且曾经做过完整备份的数据库,其状态才会显示“满足先决条件”。
选择一个用户数据库,将其加入可用性组。
(3)指定副本
在“指定副本”页,“副本”选项卡默认仅显示当前实例(主要副本)。
单击“添加副本”按钮,连接到另一台节点计算机的实例(辅助副本),将其添加到可用性组。
转到“端点”选项卡,默认将显示各节点实例(副本)已经创建过的数据库镜像端点。如果尚未创建过端点,向导将自动为这些实例创建一个名为“Hadr_endpoint”的端点,默认使用 TCP 5022 端口。
转到“备份首选项”选项卡。
转到“侦听器”选项卡。暂时不创建侦听器。
(4)选择初始数据同步
在“选择初始数据同步”页,为初始化辅助数据库选择一个选项。
(5)验证
在“验证”页显示对可用性组的验证结果。
如果遇到结果显示为“失败”的验证项目,可以检查失败的原因,修复它,然后回到此页并单击“重新运行验证”按钮。
(6)完成配置
在“摘要”页,显示刚才配置的选项。
在右下方有一个“脚本”按钮。可以单击其右侧的下拉条,选择“新查询编辑窗口”或“文件”或“剪贴板”。
单击“完成”按钮,将完成配置选项并自动跳转到“进度”页。
“进度”页显示当前正在配置的进度。完成后将自动跳转到“结果”页。
在“结果”页,单击“关闭”按钮,退出新建可用性组向导。
16.1.5 使用脚本
上述操作,使用脚本如下:
--- YOU MUST EXECUTE THE FOLLOWING SCRIPT IN SQLCMD MODE. :Connect SQLSVR1 USE [master] GO CREATE LOGIN [LOCALDOMAIN\SQLHAUser] FROM WINDOWS GO :Connect SQLSVR2 USE [master] GO CREATE LOGIN [LOCALDOMAIN\SQLHAUser] FROM WINDOWS GO :Connect SQLSVR1 USE [master] GO CREATE ENDPOINT [Hadr_endpoint] AS TCP (LISTENER_PORT = 5022) FOR DATA_MIRRORING (ROLE = ALL, ENCRYPTION = REQUIRED ALGORITHM AES) GO IF (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint') <> 0 BEGIN ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED END GO use [master] GO GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [LOCALDOMAIN\SQLHAUser] GO :Connect SQLSVR2 USE [master] GO CREATE ENDPOINT [Hadr_endpoint] AS TCP (LISTENER_PORT = 5022) FOR DATA_MIRRORING (ROLE = ALL, ENCRYPTION = REQUIRED ALGORITHM AES) GO IF (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint') <> 0 BEGIN ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED END GO use [master] GO GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [LOCALDOMAIN\SQLHAUser] GO :Connect SQLSVR1 IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='AlwaysOn_health') BEGIN ALTER EVENT SESSION [AlwaysOn_health] ON SERVER WITH (STARTUP_STATE=ON); END IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name='AlwaysOn_health') BEGIN ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START; END GO :Connect SQLSVR2 IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='AlwaysOn_health') BEGIN ALTER EVENT SESSION [AlwaysOn_health] ON SERVER WITH (STARTUP_STATE=ON); END IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name='AlwaysOn_health') BEGIN ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START; END GO :Connect SQLSVR1 USE [master] GO CREATE AVAILABILITY GROUP [HAGroup01] WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY) FOR DATABASE [SQLDB01] REPLICA ON N'SQLSVR1' WITH (ENDPOINT_URL = N'TCP://SQLSVR1.LocalDomain.Local:5022', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SECONDARY_ROLE(ALLOW_CONNECTIONS = NO)), N'SQLSVR2' WITH (ENDPOINT_URL = N'TCP://SQLSVR2.LocalDomain.Local:5022', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SECONDARY_ROLE(ALLOW_CONNECTIONS = NO)); GO :Connect SQLSVR2 ALTER AVAILABILITY GROUP [HAGroup01] JOIN; GO :Connect SQLSVR1 BACKUP DATABASE [SQLDB01] TO DISK = N'\\SQLSVR1\HAGroup\SQLDB01.bak' WITH COPY_ONLY, FORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION, STATS = 5 GO :Connect SQLSVR2 RESTORE DATABASE [SQLDB01] FROM DISK = N'\\SQLSVR1\HAGroup\SQLDB01.bak' WITH NORECOVERY, NOUNLOAD, STATS = 5 GO :Connect SQLSVR1 BACKUP LOG [SQLDB01] TO DISK = N'\\SQLSVR1\HAGroup\SQLDB01_20150613030200.trn' WITH NOFORMAT, NOINIT, NOSKIP, REWIND, NOUNLOAD, COMPRESSION, STATS = 5 GO :Connect SQLSVR2 RESTORE LOG [SQLDB01] FROM DISK = N'\\SQLSVR1\HAGroup\SQLDB01_20150613030200.trn' WITH NORECOVERY, NOUNLOAD, STATS = 5 GO :Connect SQLSVR2 -- Wait for the replica to start communicating begin try declare @conn bit declare @count int declare @replica_id uniqueidentifier declare @group_id uniqueidentifier set @conn = 0 set @count = 30 -- wait for 5 minutes if (serverproperty('IsHadrEnabled') = 1) and (isnull((select member_state from master.sys.dm_hadr_cluster_members where upper(member_name COLLATE Latin1_General_CI_AS) = upper(cast(serverproperty('ComputerNamePhysicalNetBIOS') as nvarchar(256)) COLLATE Latin1_General_CI_AS)), 0) <> 0) and (isnull((select state from master.sys.database_mirroring_endpoints), 1) = 0) begin select @group_id = ags.group_id from master.sys.availability_groups as ags where name = N'HAGroup01' select @replica_id = replicas.replica_id from master.sys.availability_replicas as replicas where upper(replicas.replica_server_name COLLATE Latin1_General_CI_AS) = upper(@@SERVERNAME COLLATE Latin1_General_CI_AS) and group_id = @group_id while @conn <> 1 and @count > 0 begin set @conn = isnull((select connected_state from master.sys.dm_hadr_availability_replica_states as states where states.replica_id = @replica_id), 1) if @conn = 1 begin -- exit loop when the replica is connected, or if the query cannot find the replica status break end waitfor delay '00:00:10' set @count = @count - 1 end end end try begin catch -- If the wait loop fails, do not stop execution of the alter database statement end catch ALTER DATABASE [SQLDB01] SET HADR AVAILABILITY GROUP = [HAGroup01]; GO GO |
16.1.6 确认
分别连接到两台节点计算机的实例,查看 SQLDB01 数据库的状态。
本文出自 “SQL Server 管理员指南” 博客,谢绝转载!