Skip to content

Commit

Permalink
collect AlwaysOn Availability Groups details when gathering health-ch…
Browse files Browse the repository at this point in the history
…eck databases info (includes data loss in seconds)
  • Loading branch information
rentadba committed May 26, 2017
1 parent c7b43a9 commit e3c26e4
Show file tree
Hide file tree
Showing 8 changed files with 4,895 additions and 3 deletions.
2 changes: 1 addition & 1 deletion source/common/tables/dbo.appConfigurations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ GO
SET NOCOUNT ON
GO
INSERT INTO [dbo].[appConfigurations] ([module], [name], [value])
SELECT 'common' AS [module], 'Application Version' AS [name], N'2017.05.25'AS [value] UNION ALL
SELECT 'common' AS [module], 'Application Version' AS [name], N'2017.05.26'AS [value] UNION ALL
SELECT 'common' AS [module], 'Default project code' AS [name], '$(projectCode)' AS [value] UNION ALL
SELECT 'common' AS [module], 'Database Mail profile name to use for sending emails' AS [name], NULL AS [value] UNION ALL
SELECT 'common' AS [module], 'Default recipients list - Reports (semicolon separated)' AS [name], NULL AS [value] UNION ALL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ CREATE TABLE #statsDatabaseDetails
[is_growth_limited] [bit] NULL
)

/*-------------------------------------------------------------------------------------------------------------------------------*/
IF object_id('#statsDatabaseAlwaysOnDetails') IS NOT NULL DROP TABLE #statsDatabaseAlwaysOnDetails
CREATE TABLE #statsDatabaseAlwaysOnDetails
(
[cluster_name] [sysname] NOT NULL,
[ag_name] [sysname] NOT NULL,
[host_name] [sysname] NOT NULL,
[instance_name] [sysname] NOT NULL,
[database_name] [sysname] NOT NULL,
[role_desc] [nvarchar](60) NULL,
[synchronization_health_desc] [nvarchar](60) NULL,
[synchronization_state_desc] [nvarchar](60) NULL,
[data_loss_sec] [int] NULL
)

------------------------------------------------------------------------------------------------------------------------------------------
--get default project code
IF @projectCode IS NULL
Expand Down Expand Up @@ -148,6 +163,14 @@ WHERE cin.[project_id] = @projectID
AND lsam.[descriptor]='dbo.usp_hcCollectDatabaseDetails'


DELETE sdaod
FROM [health-check].[statsDatabaseAlwaysOnDetails] sdaod
INNER JOIN [dbo].[catalogDatabaseNames] cdb ON cdb.[id] = sdaod.[catalog_database_id] AND cdb.[instance_id] = sdaod.[instance_id]
INNER JOIN [dbo].[catalogInstanceNames] cin ON cin.[id] = cdb.[instance_id] AND cin.[project_id] = cdb.[project_id]
WHERE cin.[project_id] = @projectID
AND cin.[name] LIKE @sqlServerNameFilter
AND cdb.[name] LIKE @databaseNameFilter

-------------------------------------------------------------------------------------------------------------------------
RAISERROR('--Step 2: Get Database Details Information....', 10, 1) WITH NOWAIT

Expand Down Expand Up @@ -404,6 +427,57 @@ WHILE @@FETCH_STATUS=0
, @strMessage
END CATCH

/* check for AlwaysOn Availability Groups configuration */
IF @SQLMajorVersion >= 12
begin
SET @queryToRun = N'WITH agDatabaseDetails AS
(
SELECT hc.[cluster_name]
, ag.[name] AS [ag_name]
, hinm.[node_name] as [host_name]
, arcn.[replica_server_name] AS [instance_name]
, adc.[database_name]
, ars.[role_desc]
, ars.[synchronization_health_desc]
, hdrs.[synchronization_state_desc]
, hdrs.[last_commit_time]
FROM sys.availability_replicas ar
INNER JOIN sys.dm_hadr_availability_replica_states ars ON ars.[replica_id]=ar.[replica_id] AND ars.[group_id]=ar.[group_id]
INNER JOIN sys.availability_groups ag ON ag.[group_id]=ar.[group_id]
INNER JOIN sys.dm_hadr_availability_replica_cluster_nodes arcn ON arcn.[group_name]=ag.[name] AND arcn.[replica_server_name]=ar.[replica_server_name]
INNER JOIN sys.dm_hadr_database_replica_states hdrs ON ar.[replica_id]=hdrs.[replica_id]
INNER JOIN sys.availability_databases_cluster adc ON adc.[group_id]=hdrs.[group_id] AND adc.[group_database_id]=hdrs.[group_database_id]
INNER JOIN sys.dm_hadr_instance_node_map hinm ON hinm.[ag_resource_id] = ag.[resource_id] AND hinm.[instance_name] = arcn.[replica_server_name]
INNER JOIN sys.dm_hadr_cluster_members hcm ON hcm.[member_name] = hinm.[node_name]
INNER JOIN sys.dm_hadr_cluster hc ON 1=1
)
SELECT a.[cluster_name], a.[ag_name], a.[host_name], a.[instance_name], a.[database_name]
, a.[role_desc], a.[synchronization_health_desc], a.[synchronization_state_desc]
, DATEDIFF(ss, a.[last_commit_time], b.[last_commit_time]) AS [data_loss_sec]
FROM agDatabaseDetails a
INNER JOIN agDatabaseDetails b ON a.[cluster_name]=b.[cluster_name] AND a.[ag_name]=b.[ag_name]
AND a.[database_name]=b.[database_name] AND b.[role_desc]=''PRIMARY'''
SET @queryToRun = [dbo].[ufn_formatSQLQueryForLinkedServer](@sqlServerName, @queryToRun)
IF @debugMode = 1 PRINT @queryToRun

BEGIN TRY
INSERT INTO #statsDatabaseAlwaysOnDetails([cluster_name], [ag_name], [host_name], [instance_name], [database_name], [role_desc], [synchronization_health_desc], [synchronization_state_desc], [data_loss_sec])
EXEC (@queryToRun)
END TRY
BEGIN CATCH
SET @strMessage = ERROR_MESSAGE()
PRINT @strMessage

INSERT INTO [dbo].[logAnalysisMessages]([instance_id], [project_id], [event_date_utc], [descriptor], [message])
SELECT @instanceID
, @projectID
, GETUTCDATE()
, 'dbo.usp_hcCollectDatabaseDetails'
, @strMessage
END CATCH
end


/* save results to stats table */
INSERT INTO [health-check].[statsDatabaseDetails]([catalog_database_id], [instance_id],
[data_size_mb], [data_space_used_percent], [log_size_mb], [log_space_used_percent],
Expand Down Expand Up @@ -456,7 +530,27 @@ WHILE @@FETCH_STATUS=0
INNER JOIN [dbo].[catalogDatabaseNames] cdn ON cdn.[database_id] = qt.[database_id]
AND cdn.[instance_id] = @instanceID
AND cdn.[project_id] = @projectID


INSERT INTO [health-check].[statsDatabaseAlwaysOnDetails]([catalog_database_id], [instance_id], [cluster_name], [ag_name]
, [role_desc], [synchronization_health_desc], [synchronization_state_desc], [data_loss_sec], [event_date_utc])
SELECT cdn.[id] AS [catalog_database_id]
, cin.[id] AS [instance_id]
, X.[cluster_name]
, X.[ag_name]
, X.[role_desc]
, X.[synchronization_health_desc]
, X.[synchronization_state_desc]
, X.[data_loss_sec]
, GETUTCDATE()
FROM #statsDatabaseAlwaysOnDetails X
INNER JOIN dbo.catalogMachineNames cmn ON cmn.[name] = X.[host_name]
INNER JOIN dbo.catalogInstanceNames cin ON cin.[name] = X.[instance_name] AND cin.[project_id] = cmn.[project_id] AND cin.[machine_id] = cmn.[id]
INNER JOIN dbo.catalogDatabaseNames cdn ON cdn.[name] = X.[database_name] AND cdn.[project_id] = cmn.[project_id] AND cdn.[instance_id] = cin.[id]
LEFT JOIN [health-check].[statsDatabaseAlwaysOnDetails] sdaod ON sdaod.[catalog_database_id] = cdn.[id] AND sdaod.[instance_id] = cin.[id]
AND sdaod.[cluster_name] = X.[cluster_name] AND sdaod.[ag_name] = X.[ag_name]
WHERE cin.[project_id] = @projectID
AND sdaod.[id] IS NULL

FETCH NEXT FROM crsActiveInstances INTO @instanceID, @sqlServerName, @sqlServerVersion
end
CLOSE crsActiveInstances
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
-- ============================================================================
-- Copyright (c) 2004-2015 Dan Andrei STEFAN (danandrei.stefan@gmail.com)
-- ============================================================================
-- Author : Dan Andrei STEFAN
-- Create date : 26.05.2017
-- Module : Database Analysis & Performance Monitoring
-- ============================================================================

-----------------------------------------------------------------------------------------------------
--Health Check: database statistics & details
-----------------------------------------------------------------------------------------------------
RAISERROR('Create table: [health-check].[statsDatabaseAlwaysOnDetails]', 10, 1) WITH NOWAIT
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[health-check].[statsDatabaseAlwaysOnDetails]') AND type in (N'U'))
DROP TABLE [health-check].[statsDatabaseAlwaysOnDetails]
GO
CREATE TABLE [health-check].[statsDatabaseAlwaysOnDetails]
(
[id] [int] IDENTITY (1, 1) NOT NULL,
[catalog_database_id] [smallint] NOT NULL,
[instance_id] [smallint] NOT NULL,
[cluster_name] [sysname] NOT NULL,
[ag_name] [sysname] NOT NULL,
[role_desc] [nvarchar](60) NULL,
[synchronization_health_desc] [nvarchar](60) NULL,
[synchronization_state_desc] [nvarchar](60) NULL,
[data_loss_sec] [int] NULL,
[event_date_utc] [datetime] NOT NULL,
CONSTRAINT [PK_statsDatabaseAlwaysOnDetails] PRIMARY KEY CLUSTERED
(
[id],
[catalog_database_id]
) ON [FG_Statistics_Data],
CONSTRAINT [FK_statsDatabaseAlwaysOnDetails_catalogDatabaseNames] FOREIGN KEY
(
[catalog_database_id]
, [instance_id]
)
REFERENCES [dbo].[catalogDatabaseNames]
(
[id]
, [instance_id]
)
)ON [FG_Statistics_Data]
GO

CREATE INDEX [IX_statsDatabaseAlwaysOnDetails_CatalogDatabaseID] ON [health-check].[statsDatabaseAlwaysOnDetails] ([catalog_database_id], [instance_id]) ON [FG_Statistics_Index]
GO
CREATE INDEX [IX_statsDatabaseAlwaysOnDetails_InstanceID] ON [health-check].[statsDatabaseAlwaysOnDetails] ([instance_id]) ON [FG_Statistics_Index]
GO
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- Copyright (c) 2004-2015 Dan Andrei STEFAN (danandrei.stefan@gmail.com)
-- ============================================================================
-- Author : Dan Andrei STEFAN
-- Create date : 35.12.2014
-- Create date : 15.12.2014
-- Module : Database Analysis & Performance Monitoring
-- ============================================================================

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
RAISERROR('Create view : [health-check].[vw_statsDatabaseAlwaysOnDetails]', 10, 1) WITH NOWAIT
GO
IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[health-check].[vw_statsDatabaseAlwaysOnDetails]'))
DROP VIEW [health-check].[vw_statsDatabaseAlwaysOnDetails]
GO

CREATE VIEW [health-check].[vw_statsDatabaseAlwaysOnDetails]
/* WITH ENCRYPTION */
AS

-- ============================================================================
-- Copyright (c) 2004-2015 Dan Andrei STEFAN (danandrei.stefan@gmail.com)
-- ============================================================================
-- Author : Dan Andrei STEFAN
-- Create date : 05.12.2014
-- Module : Database Analysis & Performance Monitoring
-- ============================================================================

SELECT cin.[project_id] AS [project_id]
, cmn.[id] AS [machine_id]
, cmn.[name] AS [machine_name]
, cin.[id] AS [instance_id]
, cin.[name] AS [instance_name]
, sdaod.[catalog_database_id]
, cdn.[database_id]
, cdn.[name] AS [database_name]
, cdn.[active]
, cdn.[state]
, cdn.[state_desc]
, sdaod.[cluster_name]
, sdaod.[ag_name]
, sdaod.[role_desc]
, sdaod.[synchronization_health_desc]
, sdaod.[synchronization_state_desc]
, sdaod.[data_loss_sec]
, sdaod.[event_date_utc]
FROM [dbo].[catalogInstanceNames] cin
INNER JOIN [dbo].[catalogMachineNames] cmn ON cmn.[id] = cin.[machine_id] AND cmn.[project_id] = cin.[project_id]
INNER JOIN [dbo].[catalogDatabaseNames] cdn ON cin.[id] = cdn.[instance_id] AND cin.[project_id] = cdn.[project_id]
INNER JOIN [health-check].[statsDatabaseAlwaysOnDetails] sdaod ON sdaod.[catalog_database_id] = cdn.[id] AND sdaod.[instance_id] = cdn.[instance_id]
GO



Loading

0 comments on commit e3c26e4

Please sign in to comment.