通过脚本获取发生错误的同步链接

本文介绍了一种SQL Server复制错误的详细排查方法,包括从MSrepl_error表中筛选符合条件的错误记录,利用sp_browsereplcmds存储过程获取错误命令详情,并通过复杂的查询逻辑来展示错误的具体来源。
use distribution 
go
declare @xact_seqno	varbinary(16)
declare @xact_seqno_varchar varchar(30)
declare @error_text  varchar(1024)
declare @command_id	int
declare @command nvarchar(max) 
declare @error_time datetime
declare @article_id	int
declare @UndelivCmdsInDistDB int
declare @i int
declare  @nEndCommandID int

declare @ErrorCode varchar(15)
set @ErrorCode=''

--从MSerpl_error获得错误清单,仅获得1小时内,且非if @@trancount > 0 rollback tran,并且command_id大于0的最后1行错误信息
select top 1 @xact_seqno=xact_seqno,@i=datalength(xact_seqno),
@command_id=command_id,@error_text=error_text,@error_time=[time]   
from dbo.MSrepl_errors with (nolock)
where error_text not like 'if @@trancount > 0 rollback tran' and 
	time >dateadd(hour,-1,GETDATE()) and 
	command_id>0
order by time desc

--格式化varchar
set @xact_seqno_varchar= master.dbo.fn_varbintohexstr(@xact_seqno)
--当@xact_seqno_varchar不为0时
if not (@xact_seqno_varchar='0x0000000000000000000000000000' or @xact_seqno_varchar is null)
begin
DECLARE @temp TABLE
( 
	 xact_seqno varbinary(16) NULL
	,originator_srvname char(40) NULL
	,originator_db char(40) NULL
	,article_id int NULL
	,type int NULL
	,partial_command int NULL
	,hashkey int NULL
	,originator_publication_id int NULL
	,originator_db_version int NULL
	,originator_lsn varbinary(16) NULL
	,command nvarchar(1024) NULL
	,command_id int NULL 
)
	INSERT INTO @temp
	( 
		 xact_seqno
		,originator_srvname
		,originator_db
		,article_id
		,type
		,partial_command
		,hashkey
		,originator_publication_id
		,originator_db_version
		,originator_lsn
		,command
		,command_id 
	) 
	--通过系统存储过程sp_browsereplcmds获得出错语句的事务id,以及错误语句的起始command_id
	EXEC sp_browsereplcmds @xact_seqno_varchar,@xact_seqno_varchar
	
	--获得结束的command_id(超过1000字节体现在输出内容中将为多行,我们使用查询下一个ESCAPE判定语句起始行) 
	set @nEndCommandID=(select MIN (command_id) from @temp where command_id>@command_id and  command like '{CALL \[%' ESCAPE '\')
	--获得完整的错处语句
	set @command=''
	if (@nEndCommandID>0)
		SELECT   @article_id=article_id,@command=@command+command
		FROM @temp 
		where command_id>=@command_id and command_id<@nEndCommandID
	else
		SELECT  @article_id=article_id,@command=@command+command
		FROM @temp 
		where command_id>=@command_id 

	--输出出错同步链的明细信息
	SELECT  
			source_Server=@@SERVERNAME ,source_db =A.publisher_db,
			source_Object_schema =A.Source_owner,source_Object_name=A.source_object,
			destination_Server=srv.name,destination_db=S.Subscriber_db,
			destination_object_schema=A.Source_owner,destination_object_name=A.destination_object,
			@command as command ,@error_time as error_time,@error_text as error_text,now_time=getdate(),
			Job_name=tb.name,Job_ID=tb.job_id,tb.publication ,@xact_seqno_varchar  as xact_seqno_varchar,@command_id   as command_id,
			TB.UndelivCmdsInDistDB,TB.profile_id
	FROM dbo.MSpublications AS P WITH (NOLOCK)
	inner join dbo.MSarticles AS A WITH (NOLOCK)
		on p.Publication_id = A.Publication_id
	INNER JOIN dbo.MSsubscriptions AS S WITH (NOLOCK)
		ON S.Publication_id = P.Publication_id	and S.article_id = a.article_id
	INNER JOIN sys.servers as srv WITH (NOLOCK)
		ON S.subscriber_id = srv.Server_id
	inner join (
		select distinct h.article_id,a.profile_id ,dh.agent_id,s.publication_id ,s.publisher_database_id,h.UndelivCmdsInDistDB,a.name,a.job_id,a.publication,s.subscriber_id
		from     dbo.MSdistribution_agents as a with(nolock)  
		inner join    dbo.MSsubscriptions as s with(nolock)   on  s.agent_id = a.id
		inner join (select agent_id, max(timestamp) as timestamp
						  from dbo.MSdistribution_history with(nolock) 
						  group by agent_id) cte 
			on cte.agent_id=a.id
		inner join dbo.MSdistribution_history dh with(nolock)  
			on dh.agent_id=cte.agent_id and dh.timestamp=cte.TIMESTAMP
		inner join dbo.MSdistribution_status  as h  with (nolock)
			on h.agent_id=cte.agent_id
		where  (s.status in (0,1) or dh.runstatus >=5 or dh.comments like '%Error %')
	) as TB on S.agent_id = TB.agent_id and a.article_id=TB.article_id
	where a.article_id=@article_id  
end
else
begin
--当然@xact_seqno_varchar为0时,表示不是语句造成的同步错误,直接返回该同步相关信息
	SELECT  
			source_Server=@@SERVERNAME ,source_db =A.publisher_db,
			source_Object_schema ='',source_Object_name='',
			destination_Server=d.srvnetname,destination_db=S.Subscriber_db,
			destination_object_schema='',destination_object_name='',
			@command as command ,@error_time as error_time,@error_text as error_text,now_time=getdate(),
			Job_name=a.name ,Job_ID=a.job_id,a.publication ,@xact_seqno_varchar  as xact_seqno_varchar,@command_id   as command_id,
			H.UndelivCmdsInDistDB as UndelivCmdsInDistDB,a.profile_id
	from dbo.MSdistribution_agents  a with(nolock) 
	inner join master.dbo.sysservers d  with(nolock) 
		on a.subscriber_id=d.srvid 
	inner join dbo.MSpublications c with(nolock) 
		on 	a.publisher_db=c.publisher_db and a.publication=c.publication
	inner join dbo.MSsubscriptions s WITH(NOLOCK)
		 on s.agent_id = a.id
	inner join (select agent_id, max(timestamp) as timestamp
				from dbo.MSdistribution_history with(nolock) 
				group by agent_id) cte 
		on cte.agent_id=a.id
	inner join dbo.MSdistribution_history dh with(nolock)  
		on dh.agent_id=cte.agent_id and dh.timestamp=cte.TIMESTAMP
	inner join dbo.MSdistribution_status  as h  with (nolock)
			on h.agent_id=cte.agent_id
	where  (s.status in (0,1) 	or dh.runstatus >=5 or dh.comments like '%Error %') and @command >0
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值