前提:本次描述的是SQL SERVER 2008R2版本,其它版本没有测试,复制类型主要是Transaction Replication和P2P复制
无论是高可用,高可扩展,还是高性能,SQLSERVER的复制分发都是一个不错的选项,配置相对容易,对前台程序的改动也少,因此使用很广泛,但是后期的日常维护,故障排错就麻烦了,
需要对复制分发的原理,元数据表等相当的了解之后才有可为,否知的话一遇到问题,不知所措,万能的解决方法便是重新初始化。本文测试的是当订阅端突然宕机,或者是人为关机,但是
发布端数据库还在不停地Insert/Update,导致链路挂起,而一旦订阅端重连上后的处理方法。本次测试分订阅端短期中断和长期中断。
publication database : mysales_normal
publication : pub_mysales_normal
publication type : transaction replication/peer-to-peer replication
subscription database : mysales_normal
一个是默认实例,一个是命令实例,参与复制分发的表为vendor.具体如下图所示:
首先我把命令实例服务和Agent关闭,然后往发布端vendor表插入两条记录
USE mysales_normal GO INSERT INTO [mysales_normal].[myinventory].[Vendor] VALUES(1,'peter','beishangguang','shanghai','40034','13458294') INSERT INTO [mysales_normal].[myinventory].[Vendor] VALUES(2,'top','yyyyyyyy','guangzhou','40034','13458294') GO
此时,logreader agent 从mysales_normal里读取两条日志文件,然后把它写入到distribution..msrepl_commands中,distribution agent 从该表中读取命令
后写入订阅端相应的vendor表中,但此时连接已中断,我们可以从replication monitor中看到相应的错误信息。
我们可以通过sp_browereplcmds来读取msrepl_commands表中的命令:
SELECT mt.publisher_db,id,article,article_id FROM distribution.dbo.MSpublisher_databases md INNER JOIN distribution.dbo.msarticles mt ON mt.publisher_db=md.publisher_db WHERE mt.publisher_db='mysales_normal' exec distribution..sp_browsereplcmds @publisher_database_id=7 , @article_id=8
可以看到这两条命令已经在msrepl_commands表中了。在replication monitor中也可看到有两条命令没有传送到distributior 中:
这时候我们重启命名实例服务,看看这两条命令能不能传到订阅端:
发现两条命令已经发送到订阅端,在来看看订阅表中的数据:
USE mysales_normal GO SELECT * FROM [mysales_normal].[myinventory].[Vendor]
已经有数据了,说明数据写入了订阅表,但当查看replication monitor中未发送命令时,发现undistributed commands还为2 ,如图所示:
根据 BOL上的解释:undistributed commands 是:还没有没有发送到订阅服务器的命令数。
The number of commands in the distribution database that have not been delivered to the selected Subscriber.
A command consists of one Transact-SQL data manipulation language (DML) statement or one data definition language (DDL) statement.
此时在replication monitor中insert tracer,发现链路是通的,而msrepl_commands中还有两条命令。
exec distribution..sp_browsereplcmds @publisher_database_id=7 , @article_id=8
这些无用的命令什么时候,被谁清理掉了?这就轮到 Distribution clean up:distribution这个job,每隔10分钟运行一次,把那些已写入到订阅端的命令清理掉.
手动运行一次,在看看结果,发现sp_browereplcmds返回空结果集了。但是通常为replication monitor这个工具监视的需要,msrepl_commands至少要保留一条记录,如图所示:
exec distribution..sp_browsereplcmds @publisher_database_id=7
可以手工删除msrepl_commands中,这个命令的一行数据,
DELETE FROM distribution.dbo.msrepl_commands WHERE publisher_database_id=7
总结:1:replication monitor 中 undistributed commands 并不能实时的反应未发送的命令,它只是显示发布项在msrepl_commands中对应的记录有多少条,Distribution clean up:distribution
这个job每隔10分钟跑一次,故 undistributed commands 有10分钟的滞后,我们只能通过Insert tracer来实时监控当前链路是否畅通,如果不畅通,可以大致判断有多少条命令挂起!
2:当订阅端重新连上后,发布服务器会自动的把挂起的命令传送到订阅端,不需要人工干预!