《Replication的犄角旮旯》系列导读
Replication的犄角旮旯(一)--变更订阅端表名的应用场景
Replication的犄角旮旯(二)--寻找订阅端丢失的记录
Replication的犄角旮旯(三)--聊聊@bitmap
Replication的犄角旮旯(四)--关于事务复制的监控
Replication的犄角旮旯(五)--关于复制identity列
Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)
Replication的犄角旮旯(七)-- 一个DDL引发的血案(下)(聊聊logreader的延迟)
Replication的犄角旮旯(八)-- 订阅与发布异构的问题
Replication的犄角旮旯(九)-- sp_setsubscriptionxactseqno,赋予订阅活力的工具
---------------------------------------华丽丽的分割线--------------------------------------------
最近经常被群里的朋友问到如何监控复制状态这样的问题;总结一下我自己的经验吧,仅供参考;
关于事务复制,一般监控的内容无外乎代理的状态(重试、失败)、复制延迟两类,而复制延迟又分为两个阶段(发布到分发、分发到订阅)
检测复制代理状态
MSdistribution_agents --其中每个在本地分发服务器上运行的分发代理对应一行。此表存储在分发数据库中。
http://msdn.microsoft.com/zh-cn/library/ms174399%28v=sql.120%29.aspx
MSdistribution_history --包含与本地分发服务器关联的分发代理的历史记录行。 此表存储在分发数据库中。
http://msdn.microsoft.com/zh-cn/library/ms179878%28v=sql.120%29.aspx
根据这两个系统表,可以查出近期分发代理的状态;
MSdistribution_agents中的id列与MSdistribution_history中的agent_id关联
MSdistribution_history中的runstatus列表示运行状态
运行状态:
1 = 启动。
2 = 成功。
3 = 正在进行。
4 = 空闲。
5 = 重试。
6 = 失败。
如果对MSdistribution_history表的time列取最近N分钟的记录,与MSdistribution_agents 做right join,则可以看出近N分钟内,是否存在不活动的分发代理;
检测复制延迟
sp_replmonitorhelpsubscription --返回发布服务器上属于一个或多个发布的订阅的当前状态信息,并为每个返回的订阅返回一行。 在分发服务器上对分发数据库执行此存储过程,用于监视复制。
http://msdn.microsoft.com/zh-cn/library/ms188073%28v=sql.120%29.aspx
用法如下:
EXEC distribution.dbo.sp_replmonitorhelpsubscription NULL,NULL,NULL,0,0,0,NULL,0
其中latency表示在事务发布中,由日志读取器代理或分发代理传播的数据更改的最长滞后时间(秒)
尽管这个值并不能明确的表示具体是哪个阶段发生的延迟(发布到分发、分发到订阅)
关于复制延迟进一步的判断
sp_replcounters --为每个发布数据库返回有关滞后时间、吞吐量和事务计数的复制统计信息。 此存储过程在发布服务器的任何数据库中执行。
http://msdn.microsoft.com/zh-cn/library/ms190486%28v=sql.120%29.aspx
其中Replicated transactions列表示日志中等待传送到分发数据库的事务数;也就是logreader等待从日志中读取的事务数。如果这个值持续增长,说明logreader正处于繁忙状态。首要检查一下VLF是否过多,或者是否写入量较大;
具体的处理办法,可以参考一下高桑的《Replication--复制延迟的诊断和解决》
msrepl_commands --包含复制的命令行数。 该表存储在分发数据库中。
http://msdn.microsoft.com/zh-cn/library/ms178611.aspx
这个表是已经从发布库日志中读取到信息,转换为复制命令存储到此表中,每个命令对应一条记录;
如果这个表的记录数过大(前提是publication中immediate_sync为false,且刚刚执行过分发清除代理时),则表明当前有较多的复制命令未完成分发,说明分发代理繁忙。需要检查一下订阅端是否存在锁、或者较多的索引,导致分发代理效率低下;
关于publication中immediate_sync属性
在默认情况下,immediate_sync是关闭的,这个属性可以在创建publication时指定,也可以在创建完毕后修改。 如果immediate_sync为true, snapshot 文件和replicated transaction将一直保留到data retention.然后才会被删除。这会导致distribution 数据库增长,复制性能下降。 所以推荐设置为false. 需要注意的时,如果一个数据库有多个publication,只要其中有一个publication的immediate_sync为true,将会导致 这个数据库的所有publication的replicated transaction的保留期都延长至data retention.
或者更准确一些,使用sp_replmonitorsubscriptionpendingcmds
sp_replmonitorsubscriptionpendingcmds -- 返回有关对事务发布的订阅的等待命令数以及处理这些命令的粗略估计时间的信息。 此存储过程针对每个返回的订阅返回一行。 在分发服务器的分发数据库上执行此存储过程,用于监视复制。
使用方法:
sp_replmonitorsubscriptionpendingcmds [ @publisher = ] 'publisher' , [ @publisher_db = ] 'publisher_db' , [ @publication = ] 'publication' , [ @subscriber = ] 'subscriber' , [ @subscriber_db = ] 'subscriber_db' , [ @subscription_type = ] subscription_type
结果集
刚刚又被朋友问到,发生延迟的时候,是否能定位到是哪些表有频繁的事务;
下面这个脚本是检索当前msrepl_commands中命令涉及表的分布情况,基本可以定位到引起延迟的对象;
如果需要检索最近N分钟的情况,按照b.entry_time在CTE中取最近的N分钟即可;
--当前msrepl_commands表中命令涉及表的分布情况
WITH cte AS(SELECT a.xact_seqno,b.entry_time,
REPLACE(CONVERT(NVARCHAR(1024),SUBSTRING(a.command,17,1024)),'[dbo].[sp_MS','') commands
FROM dbo.MSrepl_commands a(NOLOCK)
JOIN MSrepl_transactions b(NOLOCK) ON a.xact_seqno=b.xact_seqno
)
SELECT SUBSTRING(commands,9,CHARINDEX(']',commands)-9),COUNT(1) FROM cte WHERE CHARINDEX(']',commands)>9
GROUP BY SUBSTRING(commands,9,CHARINDEX(']',commands)-9)
ORDER BY COUNT(1) DESC
欢迎拍砖;