Sql-Server

如何故障轉移多個遠端伺服器上的可用性組

  • August 10, 2020

我們有許多帶有可用性組的 SQL Server 安裝。在我們的維護視窗期間,我們需要將所有 HA 組故障轉移到輔助伺服器,修補主伺服器,然後故障恢復,修補輔助伺服器。登錄到每台伺服器並執行故障轉移/故障回復工作是一個乏味的過程。

我正在尋找一種方法來自動化這個過程。有什麼方法可以將故障轉移語句從我們的中央管理伺服器執行到多個連結伺服器,並將高可用性組名稱和遠端伺服器名稱作為變數。試過這個,它不起作用:

declare 
@remote_server [char](24),
@hag_name  nvarchar(24),


set @hag_name  = 'group1'
set @remote_server = 'Server1'

execute ('ALTER AVAILABILITY GROUP ? FAILOVER', @hag_name) at @remote_server

該解決方案不使用 CMS,但我認為它會起作用。這是我放在一起的一個小腳本,用於在逗號分隔的伺服器列表中搜尋 SQL 操作符,當 DBA 被換入和換出時,這些操作符應該被更改。

我修改了多個 AG 故障轉移的腳本。您可以對其進行調整以適應您的特定環境。

您必須建構輔助伺服器和可用性組的逗號分隔列表:server1,ag1,server2,ag2,…. …並將其插入程式碼中。

該腳本的輸出是可執行程式碼。此範例腳本的輸出應如下所示:

(1 row affected)
:CONNECT server1
ALTER AVAILABILITY GROUP [L1] FAILOVER;
GO

:CONNECT server2
ALTER AVAILABILITY GROUP [L2] FAILOVER;
GO

:CONNECT server3
ALTER AVAILABILITY GROUP [L3] FAILOVER;
GO

:CONNECT server4
ALTER AVAILABILITY GROUP [L4] FAILOVER;
GO

然後將其複制/粘貼到新的 SSMS 視窗中,刪除非 TSQL 行,如“(受影響的 1 行)”,在 SSMS 中切換到 SQLCMD 模式,然後執行。

這個腳本真正需要的是一種智能的方式來知道哪個伺服器是次要的,因此對於 CDL,您不必知道它。我將嘗試將其放在一起並在此處發布編輯。

當然,在幾個豚鼠伺服器上進行測試。

/*
This script will create a TSQL script that you can run separately in SQLCMD mode. 

Steps:
1. Edit @Servers with a comma delimted list of your servers.
2. Edit @SearchVariable1 and @SearchVariable2 with the search variables. 
       If you want to search for only 1 string, then make both variables that string.
       For example 'kanjana', which is part of the name of the DBA who had this set of servers before me. 
   You can add more SearchVariableN variables. Edit the dynamic SQL statement. 
3.  Edit the dynamic SQL to do whatever you need.
4. Copy and paste the result into a new window, specify Query | SQLCMD mode, and execute.
   Remove any non-TSQL lines, such as '(1 row affected)'
5. If logical, you can re-run the script to check the results.


*/

USE MSDB
GO

IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'SplitString')
   AND xtype IN (N'TF'))
DROP FUNCTION SplitString
-- SELECT * FROM sysobjects WHERE id = object_id(N'SplitString')
GO

CREATE FUNCTION [dbo].[SplitString]
(      
     @Input NVARCHAR(MAX),  
     @Character CHAR(1)=','  
)  
RETURNS @Output TABLE (  
     Item NVARCHAR(1000)  
)  
AS  
BEGIN  
     DECLARE @StartIndex INT, @EndIndex INT  

     SET @StartIndex = 1  
     IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character  
     BEGIN  
           SET @Input = @Input + @Character  
     END  

     WHILE CHARINDEX(@Character, @Input) > 0  
     BEGIN  
           SET @EndIndex = CHARINDEX(@Character, @Input)  

           INSERT INTO @Output(Item)  
           SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)  

           SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))  
     END  

     RETURN  
END
GO


-- User configuration variables:
DECLARE @Servers VARCHAR(MAX) = ''

-- ************ Edit these variables:
SET @Servers = @Servers +
   'server1,L1,server2,L2,server3,L3,server4,L4' 

-- ************ 

-- other variables:
DECLARE @ThisServer VARCHAR(100)
DECLARE @ThisL VARCHAR(100)
DECLARE @SQL VARCHAR(MAX) = ''
DECLARE @B CHAR(2) = CHAR(13) + CHAR(10) 


DECLARE MyCursor CURSOR
   FOR SELECT * FROM dbo.SplitString(@Servers,',')
OPEN MyCursor 

FETCH NEXT FROM MyCursor INTO @ThisServer
FETCH NEXT FROM MyCursor INTO @ThisL

WHILE @@FETCH_STATUS = 0
BEGIN
   -- PRINT @ThisServer
   SET @SQL = @SQL + ':CONNECT ' + @ThisServer + @B
   SET @SQL = @SQL + 'ALTER AVAILABILITY GROUP [' + @ThisL + '] FAILOVER;'
   SET @SQL = @SQL + @B + 'GO' + @B + @B

   FETCH NEXT FROM MyCursor INTO @ThisServer
   FETCH NEXT FROM MyCursor INTO @ThisL
END

PRINT @SQL

CLOSE MyCursor
DEALLOCATE MyCursor



IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'SplitString')
   AND xtype IN (N'TF'))
DROP FUNCTION SplitString

您可以使用 PowerShell 和dbatools模組為您編排。基本上,您通過 PowerShell查詢您的 CMS以獲取伺服器列表,然後遍歷該列表並使用Get-DbaAvailabilityGroup獲取每台伺服器上的可用性組。然後可以將其傳遞給Invoke-DbaAgFailover以執行故障轉移。

您可以擴展 PowerShell 以檢查故障轉移之前的正確 AG 狀態等內容,並且 dbatools 函式具有內置邏輯,可在預設情況下安全地執行故障轉移(無數據失去)。

將此腳本設置為您的 CMS 伺服器上的代理作業,並按計劃或手動執行它作為修補過程的一部分。通過從 CMS 獲取伺服器並使用 Get-DbaAvailabilityGroup,只要您已將副本添加到 CMS,任何新的 AG 都將被自動處理。

引用自:https://dba.stackexchange.com/questions/237078