info@techdevops.com | 437-991-3573 | Data Engineering Services
TechDevOps.com
Resources Tools
Experts in Microsoft SQL Server on Windows, Linux, Containers | Clusters, Always On, FCI | Migrations, Cloud, Performance



SQL Server Replication Get Undistributed Commands
by BF (Principal Consultant; Architecture; Engineering)
2016-07-20









Solution: Get Total Undistributed Commands Programmatically (Per Subscriber)


Replication Monitor:







Step 1: Create a permanent logging table to store the output. Used for baseline & alerting.


CREATE TABLE [dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS](
[LogID] [int] IDENTITY(1,1) NOT NULL,
[PublisherDB] [varchar](50) NULL,
[Publication] [varchar](100) NULL,
[Subscriber] [varchar](100) NULL,
[PendingCMDCount] [int] NULL,
[EstimatedProcessTime_sec] [int] NULL,
[InsertedDate] [datetime] NULL,
CONSTRAINT [PK_LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS] PRIMARY KEY CLUSTERED
(
[LogID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO



Step 2: Create a stored procedure to get & log the number of Transactional Replication Undistributed Commands.


/****** Object: StoredProcedure [dbo].[Replication_Get_PendingCMDCount_InsertPublicationNameHere] Script Date: 7/20/2016 9:57:39 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

Create Procedure [dbo].[Replication_Get_PendingCMDCount_InsertPublicationNameHere]
@Debug bit = 0
as

set nocount on

/*
Select * from [dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS]
*/

--Method 1:
--Exec [sys].[sp_replmonitorsubscriptionpendingcmds] @publisher,@publisher_db,@publication,@subscriber,@publisher_db,@subscription_type
/*
Cannot use this method to easily log into a table due to Error: Cannot Nest Insert Into Exec calls - because Insert into Exec is already used in
sp_replmonitorsubscriptionpendingcmds.
*/

--Method 2:
/*
Can use this easily to log into a logging table.
*/

Declare @publication sysname
Declare @publisher sysname
Declare @publisher_id int
Declare @publisher_db sysname
Declare @subscriber_db sysname
Declare @subscription_type int = 0
Declare @subscriber_id int
Declare @subscriber sysname
Declare @agent_id int
Declare @lastrunts timestamp
Declare @xact_seqno varbinary(16)
Declare @avg_rate float
Declare @MaxID int
Declare @PriorMaxLogIDLogged int

Set @PriorMaxLogIDLogged = (Select Max(LogID) from [OPS].[dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS])

SET @publication = 'xyz'

Declare @PubDetails Table (ID Int Identity(1,1), Publisher sysname, PublisherDB sysname, Subscriber sysname, SubscriberDB sysname)
Insert into @PubDetails (Publisher, PublisherDB, Subscriber, SubscriberDB)
SELECT t5.srvname, t1.publisher_db, t6.srvname,t3.subscriber_db
FROM [distribution].[dbo].[MSpublications] t1
INNER JOIN [distribution].[dbo].[MSdistribution_agents] t3 on t1.publication = t3.publication
INNER JOIN [MSDB].[dbo].[MSagent_profiles] t4 on t3.profile_id = t4.profile_id
INNER JOIN master..sysservers t5 ON t1.publisher_id = t5.srvid
INNER JOIN master..sysservers t6 ON t3.subscriber_id = t6.srvid
WHERE t1.publication = @publication
ORDER BY t6.srvname asc

--Select * from @PubDetails

If Exists (Select 1 from @PubDetails)
Begin
Set @MaxID = (Select Max(ID) from @PubDetails)
End

While @MaxID > 0
Begin

Set @publisher = (Select top 1 Publisher from @PubDetails where ID = @MaxID)
Set @publisher_db = (Select top 1 PublisherDB from @PubDetails where ID = @MaxID)
Set @subscriber_db = (Select top 1 SubscriberDB from @PubDetails where ID = @MaxID)

Set @subscriber = (Select top 1 Subscriber from @PubDetails where ID = @MaxID)
select @publisher_id = server_id from sys.servers where upper(name) = upper(@publisher)
select @subscriber_id= server_id from sys.servers where upper(name) = upper(@subscriber)
select @agent_id=id from Distribution.dbo.MSdistribution_agents where publisher_id = @publisher_id and publisher_db = @publisher_db and publication in (@publication, 'ALL')
and subscriber_id = @subscriber_id and subscriber_db = @subscriber_db and subscription_type = @subscription_type
select @lastrunts = max(timestamp) from Distribution.dbo.MSdistribution_history where agent_id = @agent_id
select @xact_seqno = xact_seqno,@avg_rate = delivery_rate from Distribution.dbo.MSdistribution_history where agent_id = @agent_id and timestamp = @lastrunts
select @avg_rate = isnull(avg(delivery_rate),0.0) from Distribution.dbo.MSdistribution_history where agent_id = @agent_id

--Select @subscriber, @publisher_id, @subscriber_id, @agent_id, @lastrunts, @xact_seqno, @avg_rate

Declare @countab Table (pendingcmdcount int)
Insert into @countab (pendingcmdcount)
Exec Distribution.sys.sp_MSget_repl_commands @agent_id = @agent_id,@last_xact_seqno = @xact_seqno,@get_count = 2,@compatibility_level = 9000000

--Select * from @countab

Insert into [OPS].[dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS] ([PublisherDB],[Publication],[Subscriber],[PendingCMDCount],[EstimatedProcessTime_sec],[InsertedDate])
Select @publisher_db as 'Publisher', @publication as 'Publication', @subscriber as 'Subscriber', pendingcmdcount, N'estimatedprocesstime' = case when (@avg_rate != 0.0) then cast((cast(pendingcmdcount as float) / @avg_rate) as int) else pendingcmdcount end, getdate() from @countab

Delete from @PubDetails where ID = @MaxID
Set @MaxID = (Select Max(ID) from @PubDetails)
--Delete from @PubDetails where Subscriber = @subscriber
Delete from @countab
End

If @Debug = 1
Begin
Select * from [OPS].[dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS] where LogID > @PriorMaxLogIDLogged
End
GO


Step 3: Call stored procedure from withing a SQL Job

Job Step 1:

Exec dbo.Replication_Get_PendingCMDCount_InsertPublicationNameHere

Job Step 2:

If Exists (Select 1 from [OPS].[dbo].[LOG_TRANSACTIONAL_REPLICATION_UNDISTRIBUTED_COMMANDS] where PendingCMDCount > 200000
and InsertedDate > dateadd(MI,-5,getdate()))
Begin
RAISERROR('Transactional Replication Error Alert - Undistributed Commands High - InsertPublicationNameHere!', 16, 1)
End





That's it !!!


Extra: Check Delivery Rate: http://techdevops.com/Article.aspx?CID=160