起因:
1. 将一个存储过程发布并启用快照时(可更新订阅),分发事务表和命令表插入了重复键导致冲突,程序不断重试。
队列读取器不断报错,同时也导致分发代理出错不能进行分发。错误如下:
错误消息:
进程无法在“ServerName”上执行“sp_MSadd_replcmds”。 (源: MSSQLServer,错误号: 1007)
不能在具有唯一索引 'ucMSrepl_transactions' 的对象 'dbo.MSrepl_transactions' 中插入重复键的行。重复的键值为 (8, 0x0012061a0000190a0052)。
不能在具有唯一索引 'ucMSrepl_commands' 的对象 'dbo.MSrepl_commands' 中插入重复键的行。重复的键值为 (8, 0x0012061a0000190a0052, 1)。
不能在具有唯一索引 'ucMSrepl_commands' 的对象 'dbo.MSrepl_commands' 中插入重复键的行。重复的键值为 (8, 0x0012061a0000190a0052, 2)。
不能在具有唯一索引 'ucMSrepl_commands' 的对象 'dbo.MSrepl_commands' 中插入重复键的行。重复的键值为 (8, 0x0012061a0000190a0052, 3)。
不能在具有唯一索引 'ucMSrepl_commands' 的对象 'dbo.MSrepl_commands' 中插入重复键的行。重复的键值为 (8, 0x0012061a0000190a0052, 4)。
(源: MSSQLServer,错误号: 1007)
未将批提交到分发服务器。 (源: MSSQL_REPL,错误号: MSSQL_REPL22020)
The last step did not log any message! (源: MSSQL_REPL,错误号: MSSQL_REPL22037)
(按理存储过程的发布是不会影响到表的,但是这里出现问题了。可能情况是分发表插入因未使用事务保证完整性,遇到某问题导致事务中断停止,然后日志读取器又重新读写到分发表中,导致冲突!)
2. 由于错误一直进行,于是就将该事务和命令从分发表中删除!
DELETE FROM distribution.dbo.MSrepl_commands
WHERE publisher_database_id=8 AND xact_seqno=0x0012061a0000190a0052
DELETE FROM distribution.dbo.MSrepl_transactions
WHERE publisher_database_id=8 AND xact_seqno=0x0012061a0000190a0052
删除之后,日志读取器又出现新的问题了!(这个错误是可以模拟重现的,以下的错误信息可能不是在相同的环境了,因为测试过几次不记得保留哪份了!)
错误消息:
进程无法在“ServerName”上执行“sp_repldone/sp_replcounters”。 (源: MSSQL_REPL,错误号: MSSQL_REPL20011)
为 repldone 日志扫描指定的 LSN {00000000:00000000:0000} 出现在日志 {00000217:00000013:000a} 中的当前复制开始之前。 (源: MSSQLServer,错误号: 18768)
进程无法设置上次分发的事务。 (源: MSSQL_REPL,错误号: MSSQL_REPL22017)
进程无法在“ServerName”上执行“sp_repldone/sp_replcounters”。 (源: MSSQL_REPL,错误号: MSSQL_REPL22037)
这导致了扫描日志的序列号不连续了!~
没办法,最终将所有事务标识为已分发跳过了!因为本人环境允许,使用的是可更新订阅,用户都在订阅库操作,所以分发的数据是没什么用的,但是系统还是要判断。
错误参考:
最终解决办法:
exec sp_repldone @xactid = NULL, @xact_segno = NULL, @numtrans = 0, @time = 0, @reset = 1
exec sp_replflush