SQL复制“未找到行”错误

时间:2009-02-19 22:46:25

标签: sql-server replication

我在两个数据库之间运行事务复制。我担心它们会略微不同步,但我不知道哪些记录会受到影响。如果我知道,我可以在用户端手动修复它。

SQL Server正在给我这条消息:

  

应用复制命令时,在订阅服务器上找不到该行。 (来源:MSSQLServer,错误号:20598)

我环顾四周试图找出哪个表格,甚至更好的是什么记录导致了这个问题,但我无法在任何地方找到这些信息。

到目前为止,我发现的最详细的数据是:

  

交易顺序号:0x0003BB0E000001DF000600000000,命令ID:1

但是如何从中找到表格和行?有什么想法吗?

8 个答案:

答案 0 :(得分:11)

这为您提供了错误表格

use distribution
go

select * from dbo.MSarticles
where article_id in (
    select article_id from MSrepl_commands
    where xact_seqno = 0x0003BB0E000001DF000600000000)

这将为您提供命令(以及命令执行的主键(即行))

exec sp_browsereplcmds 
@xact_seqno_start = '0x0003BB0E000001DF000600000000', 
@xact_seqno_end = '0x0003BB0E000001DF000600000000'

答案 1 :(得分:9)

我将以最终使用的解决方法回答我自己的问题。

不幸的是,我无法通过SQL Server复制接口(或事件日志)找出导致问题的表。它只是没说。

所以接下来我想到的是,“即使出现错误,如果我可以继续复制怎么办?”瞧,有一种方法。事实上,这很容易。有一个特殊的分发代理配置文件称为“继续数据一致性错误”。如果启用它,那么这些类型的错误将被记录并传递。一旦通过应用事务并可能记录错误(我只遇到两个),那么您可以返回并使用RedGate SQL Data Compare(或其他一些工具)来比较您的两个数据库,对订阅者进行任何更正,然后开始复制再次运行。

请记住,为了实现这一点,您的发布数据库需要在您分配和修复订阅者数据库的过程中保持“安静”。幸运的是,在这种情况下,我有这种奢侈。

答案 2 :(得分:3)

如果您的数据库不是非常大,我会停止复制,重新创建快照,然后重新启动复制。这个technet article描述了这些步骤。

如果由于用户意外更改副本上的数据而导致其不同步,我会设置必要的权限来阻止此操作。

replication article值得一读。

答案 3 :(得分:1)

使用此查询查找不同步的文章:

USE [distribution]

select * from dbo . MSarticles 
where article_id IN ( SELECT Article_id from MSrepl_commands 
where xact_seqno = 0x0003BB0E000001DF000600000000)

答案 4 :(得分:0)

当然,如果您在复制失败时检查错误,它还会告诉您哪条记录出错,您可以从核心系统中提取该数据,然后将其插入订阅者。

这比跳过错误更好,因为SQL数据比较它会锁定表进行比较,如果你有数百万行,这可能需要很长时间才能运行。

的Tris

答案 5 :(得分:0)

将配置文件更改为“继续数据一致性错误”并不总是有效。显然它会减少或消除错误,但是你不会得到完整的数据。它将跳过发生错误的行,因此无法获得准确的数据。

答案 6 :(得分:0)

以下检查解决了我的问题

  • 检查所有复制SQL代理作业是否正常工作,如果没有启动它们。
    • 在我的情况下,由于某些DBA因为阻塞问题而在几个小时之前发生了一些被杀的会话而被停止了
  • 在很短的时间内订阅的所有数据都被更新,没有 复制监视器中的其他错误
  • 在我的情况下,以上所有查询都没有返回任何内容

答案 7 :(得分:0)

此错误通常发生在订阅服务器上不存在特定记录且主服务器上的相同记录执行的更新或删除命令以及也在订阅服务器上复制的情况下。

由于此记录在订阅者上不存在,因此复制会引发错误"未找到行"

解决此错误以使复制恢复正常运行状态:

我们可以查看以下查询,发布者的请求是更新还是删除声明:

USE [distribution]

SELECT *
FROM   msrepl_commands 
WHERE  publisher_database_id = 1
       AND command_id = 1
       AND xact_seqno = 0x00099979000038D6000100000000

我们可以从上面的查询中获取artical id信息,可以传递给proc:

EXEC Sp_browsereplcmds
  @article_id = 813,
  @command_id = 1,
  @xact_seqno_start = '0x00099979000038D60001',
  @xact_seqno_end = '0x00099979000038D60001',
  @publisher_database_id = 1

上面的查询将提供有关的信息,无论是更新语句还是删除语句。

  1. 如果删除声明
  2. 该记录可以直接从msrepl_commands对象中删除,这样复制就不会重试记录

    DELETE FROM msrepl_commands
    WHERE  publisher_database_id = 1
           AND command_id =1
           AND xact_seqno = 0x00099979000038D6000100000000 
    
    1. 如果是更新声明:
    2. 您需要手动将该记录从发布者数据库插入订户数据库: