第三篇――第二部分――第五文配置SQLServer镜像――域环境SQLServer镜像日常维护(四)

2014-11-24 09:55:53 · 作者: · 浏览: 5
ch loop = 5 seconds -- 60 loops = 5 minutes @MaxCounter INT = 60 , -- 0 = Execute it, 1 = Output SQL that would be executed @Debug BIT = 0 AS DECLARE @SQL NVARCHAR(1000) , @MaxID INT , @CurrID INT , @DMState INT , @SafeCounter INT , @PartnerServer SYSNAME , @SafetyLevel INT , @TrustWorthyOn BIT , @DBOwner SYSNAME , @Results INT , @ErrMsg VARCHAR(500) , @Print NVARCHAR(1000) DECLARE @Databases TABLE ( DatabaseID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY , DatabaseName SYSNAME NOT NULL , PartnerServer SYSNAME NOT NULL , SafetyLevel INT NOT NULL , TrustWorthyOn BIT NOT NULL , DBOwner SYSNAME NULL ) SET NOCOUNT ON INSERT INTO @Databases ( DatabaseName , PartnerServer , SafetyLevel , TrustWorthyOn , DBOwner ) SELECT D.name , DM.mirroring_partner_instance , DM.mirroring_safety_level , D.is_trustworthy_on , SP.name FROM sys.database_mirroring DM INNER JOIN sys.databases D ON D.database_id = DM.database_id LEFT JOIN sys.server_principals SP ON SP.sid = D.owner_sid WHERE DM.mirroring_role = 1 AND -- Principal role DM.mirroring_state IN ( 2, 4 ) AND -- Synchronizing, Synchronized ( D.name = @DBName OR @DBName IS NULL ) IF NOT EXISTS ( SELECT 1 FROM @Databases ) AND @DBName IS NULL BEGIN RAISERROR ('There were no mirroring principals found on this server.', 1, 1); END IF NOT EXISTS ( SELECT 1 FROM @Databases ) AND @DBName IS NOT NULL BEGIN RAISERROR ('Database [%s] was not found or is not a mirroring principal on this server.', 1, 1, @DBName); END SELECT @MaxID = MAX(DatabaseID) , @CurrID = 1 FROM @Databases -- Set Safety to Full on all databases first, if needed WHILE @CurrID <= @MaxID BEGIN SELECT @DBName = DatabaseName , @PartnerServer = PartnerServer , @SafetyLevel = SafetyLevel FROM @Databases WHERE DatabaseID = @CurrID -- Make sure linked server to mirror exists EXEC @Results = dbo.dba_ManageLinkedServer @ServerName = @PartnerServer, @Action = 'create' IF @Results <> 0 BEGIN RAISERROR ('Failed to create linked server to mirror instance [%s].', 1, 1, @PartnerServer); END IF @SafetyLevel = 1 BEGIN SET @SQL = 'Alter Database ' + QUOTENAME(@DBName) + ' Set Partner Safety Full;' SET @Print = 'Setting Safety on for database ' + QUOTENAME(@DBName) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END SET @CurrID = @CurrID + 1 END -- Reset @CurrID to 1 SET @CurrID = 1 -- Pause momentarily WAITFOR DELAY '0:00:03'; -- Failover all databases WHILE @CurrID <= @MaxID BEGIN SELECT @DBName = DatabaseName , @DMState = DM.mirroring_state , @SafeCounter = 0 , @SafetyLevel = SafetyLevel FROM @Databases D INNER JOIN sys.database_mirroring DM ON DM.database_id = DB_ID(D.DatabaseName) WHERE DatabaseID = @CurrID WHILE @DMState = 2 AND -- Synchronizing @SafeCounter < @MaxCounter BEGIN WAITFOR DELAY '0:00:05'; SELECT @DMState = mirroring_state , @SafeCounter = @SafeCounter + 1 FROM sys.database_mirroring WHERE database_id = DB_ID(@DBName) END IF @DMState = 2 AND @SafeCounter = @MaxCounter BEGIN RAISERROR('Synchronization timed out for database [%s]. Please check and fail over manually.', 1, 1, @DBName); IF @SafetyLevel = 1 BEGIN SET @SQL = 'Alter Database ' + QUOTENAME(@DBName) + ' Set Partner Safety Full;' SET @Print = 'Setting Safety Full for database ' + QUOTENAME(@DBName) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END END ELSE BEGIN SET @SQL = 'Alter Database ' + QUOTENAME(@DBName) + ' Set Partner Failover;' SET @Print = 'Failing over database ' + QUOTENAME(@DBName) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END SET @CurrID = @CurrID + 1 END -- Reset @CurrID to 1 SET @CurrID = 1 -- Pause momentarily WAITFOR DELAY '0:00:03'; -- Set safety level and db owner on failed over databases WHILE @CurrID <= @MaxID BEGIN SELECT @DBName = DatabaseName , @PartnerServer = PartnerServer , @SafetyLevel = SafetyLevel , @TrustWorthyOn = TrustWorthyOn , @DBOwner = DBOwner , @DMState = DM.mirroring_state , @SafeCounter = 0 FROM @Databases D INNER JOIN sys.database_mirroring DM ON DM.database_id = DB_ID(D.DatabaseName) WHERE DatabaseID = @CurrID -- Make sure linked server to mirror exists EXEC @Results = dbo.dba_ManageLinkedServer @ServerName = @PartnerServer, @Action = 'create' WHILE @DMState = 2 AND -- Synchronizing @SafeCounter < @MaxCounter BEGIN WAITFOR DELAY '0:00:05'; SELECT @DMState = mirroring_state , @SafeCounter = @SafeCounter + 1 FROM sys.database_mirroring WHERE database_id = DB_ID(@DBName) END IF @DMState = 2 AND @SafeCounter = @MaxCounter BEGIN RAISERROR('Synchronization timed out for database [%s] after failover. Please check and set database options manually.', 1, 1, @DBName); END ELSE BEGIN -- Turn safety off if it was originally off IF @SafetyLevel = 1 BEGIN SET @SQL = 'Alter Database ' + QUOTENAME(@DBName) + 'Set Partner Safety Off;' SET @SQL = 'Exec ' + QUOTENAME(@PartnerServer) + '.master.sys.sp_executesql N''' + @SQL + ''';'; SET @Print = 'Setting Safety off for database ' + QUOTENAME(@DBName) + ' on server ' + QUOTENAME(@PartnerServer) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END -- Set TrustWorthy property on if it was originally on IF @TrustWorthyOn = 1 BEGIN SET @SQL = 'Alter Database ' + QUOTENAME(@DBName) + ' Set TrustWorthy On;' SET @SQL = 'EXEC ' + QUOTENAME(@PartnerServer) + '.master.sys.sp_executesql N''' + @SQL + ''';'; SET @Print = 'Setting TrustWorthy On for database ' + QUOTENAME(@DBName) + ' on server ' + QUOTENAME(@PartnerServer) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END -- Change database owner if different than original SET @SQL = 'If Exists (Select 1 From sys.databases D' + CHAR(10) + CHAR(9) + 'Left Join sys.server_principals P' + ' On P.sid = D.owner_sid' + CHAR(10) + CHAR(9) + 'Where P.name Is Null' + CHAR(10) + CHAR(9) + 'Or P.name <> ''' + @DBOwner + ''')' + CHAR(10) + CHAR(9) + 'Exec ' + QUOTENAME(@DBName) + '..sp_changedbowner ''' + @DBOwner + ''';' SET @SQL = REPLACE(@SQL, '''', '''''') SET @SQL = 'Exec ' + QUOTENAME(@PartnerServer) + '.master.sys.sp_executesql N''' + @SQL + ''';'; SET @Print = 'Changing Database owner to ' + QUOTENAME(@DBOwner) + ' for database ' + QUOTENAME(@DBName) + ' on server ' + QUOTENAME(@PartnerServer) + '.'; IF @Debug = 0 BEGIN PRINT @Print EXEC sp_executesql @SQL END ELSE BEGIN PRINT '-- ' + @Print PRINT @SQL; END END SET @CurrID = @CurrID + 1 END

自动故障转移 :

自动故障转移要考虑几个问题:1、伙伴服务器上的作业、维护计划等或者其他外部资源。2、应用程序依赖的库是否也同时转移,不管是否需要。3、账号

针对这些问题,可以使用Windows Management Instrumentation(WMI)命名空间来发送警告。可以通过SSMS打开,如图:

image

然后配置WMI事件:

image


然后配置响应页:

image

最后填写警告信息:image
通过这个警告,可以创建一些维护作业响应自动故障转移中的潜在问题。除此之外,还可以用Service broker、Powershell等工具来监控。针对详细的监控,可以看下一文:http://blog.csdn.net/dba_huangzj/article/details/26846203