AlwaysOn Availability Groups – Query to Find Latency Part 2

Sometimes there is a need to maintain some historical content on how current your Availability Group is performing. The following script builds off the original script in Part 1. It populates a global temp table with information every minute. I really got the idea from Brent Ozar’s sp_SQL Blitz. I took the road of least intrusive by creating the ##LatencyCheck_tbl global temp table. Sergey Gigoyan has a good post on global temp tables and good links at the end of the post, too.

The ##LatencyCheck_tbl temp table is populated after 1 minute and every minute until cancelled. Need to make sue the table gets dropped after you have done you analysis. It is a good idea to keep an eye on the size of the table, too (execute sp_spaceused ‘##LatencyCheck_tbl’). Like any temp table, service restart will drop the table the process cancelled. If this is something you would like always run. you can look into creating a SQL Agent job or even a procedure that auto starts. I don’t suggest doing that. If you do choose to do so, you should make sure you monitor of have a process in place to reduce the size of the temp table. Also, look into grabbing Perfmon counters and Extended Events. Everything has overhead and we do not want to succumb to the “Watcher Effect”..DAH! DAH! [Organ music].

Create tempdb table to capture AG metrics. 
It will run until cancelled.
After ##LatencyCheck_tbl data is exported, drop table.
Example Query below.
USE tempdb

-- Remove exist table if found
IF OBJECT_ID ('tempdb..##LatencyCheck_tbl','u' ) IS NOT NULL
DROP TABLE ##LatencyCheck_tbl

-- create temp table
CREATE TABLE ##LatencyCheck_tbl
[Last Commit Time] varchar(20),
[Time Behind Primary] varchar(30),
[Redo Queue Size] varchar(25),
[Estimated Completion Time] varchar(20),
[Estimated Recovery Time Minutes] varchar(20),
[Estimated Recovery Time Seconds] varchar(12),
[SampleTime] DATETIME

Use tempdb
-- Create GOTO loop


		WAITFOR DELAY '00:01:00'; -- Execute every 1 minute
		INSERT ##LatencyCheck_tbl
		Convert(VARCHAR(20),last_commit_time,22) AS [Last Commit Time],
		CAST(((DATEDIFF(s,last_commit_time,GetDate()))/3600) as varchar) + 'hour(s),' + CAST((DATEDIFF(s,last_commit_time,GetDate())%3600)/60 as varchar) + 'min, '+ CAST((DATEDIFF(s,last_commit_time,GetDate())%60) as varchar) + ' sec' AS [Time Behind Primary],
		CAST(redo_queue_size as VARCHAR(25)) AS [Redo Queue Size],
		CONVERT(VARCHAR(20),DATEADD(mi,(redo_queue_size/redo_rate/60.0),GETDATE()),22) AS [Estimated Completion Time],
		CAST(CAST((redo_queue_size/redo_rate/60.0) as decimal(10,2)) as VARCHAR(20)) AS [Estimated Recovery Time Minutes],
		CAST((redo_queue_size/redo_rate) as VARCHAR(12)) AS [Estimated Recovery Time Seconds],
		GETDATE() [SampleTime]
		from sys.dm_hadr_database_replica_states
		WHERE last_redone_time is not null

GOTO RepeatLoop -- Start process over

Now we have the proces running, we can use the following to query the output. From another SSMS window, execute the following query. I left some of the WHERE clause commented to show some examples.

USE tempdb

	CONVERT(VARCHAR(25),CAST([SampleTime] as DATETIME),22) [SampleTime],
	[Last Commit Time],
	[Time Behind Primary],
	[Redo Queue Size],
	[Estimated Completion Time],
	[Estimated Recovery Time Minutes],
	[Estimated Recovery Time Seconds],
	--CAST([Redo Queue Size]as BIGINT)/CAST([Estimated Recovery Time Seconds] as BIGINT) [Redo_Rate (REDO_QueueSize/EstRecTimeSec)],
	DATEDIFF(second,[Last Commit Time],[SampleTime] )[Diff_Last_Commit_CurrentTime_sec]
FROM ##LatencyCheck_tbl
WHERE 1 = 1
AND [SampleTime] >= DATEADD(MINUTE, -480, GETDATE())
--AND [SampleTime] >= CONVERT(VARCHAR(10),GETDATE()-1,121)
--and( DATEPART(hour,CAST([SampleTime] as datetime)) < =3 -- less than 4 AM
--OR DATEPART(hour,CAST([SampleTime] as datetime)) >=19
--) -- Greater than 7 PM


Tiny URL for this post:

Share the joy

Comments are closed.