当前未向订阅服务器传递数据

如果当前似乎未向订阅服务器传递数据,主要有两大原因:

  • 由于筛选、某种代理问题或其他复制错误,当前未应用数据。

  • 应用数据后,正在订阅服务器上将其删除。

说明

有多种原因可能会导致当前未向订阅服务器传递数据:

  • 表已经过筛选,没有要传递到指定订阅服务器的更改。

  • 代理未运行或由于错误导致失败。

  • 事务订阅初始化未使用快照,并且创建发布后发布服务器上出现了更改。

  • 对事务发布的存储过程执行的复制会在订阅服务器上产生不同的结果。

  • 事务项目使用的 INSERT 存储过程中包含一个未满足的条件。

  • 数据被用户、复制脚本或其他应用程序删除。

  • 数据被触发器删除,或者触发器包含 ROLLBACK 语句。

用户操作

在试图诊断当前未向订阅服务器传递数据的原因之前,我们建议用验证实用工具或 tablediff 实用工具验证是否缺行:

  • 如果分发代理或合并代理能够运行,请通过运行二进制校验和验证来确定数据是否已丢失。还可以使用行计数验证,但是此方法无法显示数据内容的差异。有关详细信息,请参阅验证已复制的数据

  • 如果分发代理或合并代理无法运行,则可以运行 tablediff 实用工具来确定是否缺少数据。有关对复制表使用此实用工具的信息,请参阅如何比较所复制表的差异(复制编程)

找出缺少数据的原因

针对“说明”部分中列出的原因,可以采取下列操作:

  • 表已经过筛选,没有要传递到指定订阅服务器的更改。

    未复制订阅服务器上缺少的行可能是因为它们不符合发布的筛选条件。所有类型的复制都支持静态筛选,而合并复制还支持参数化筛选器和联接筛选器。有关详细信息,请参阅筛选已发布数据。如果要筛选发布中的项目,请执行下列过程,并验证筛选子句的值:

    用筛选子句确定是否某些缺少的行符合筛选条件。例如,可以对发布服务器上的表执行筛选子句并确定返回的数据是否与订阅服务器上的数据匹配。

  • 代理未运行或由于错误导致失败:

  • 事务订阅初始化未使用快照,并且创建发布后发布服务器上出现了更改:

    • 如果让发布能够从备份中初始化,则一旦创建了发布,就会在发布数据库日志中跟踪对已发布表的更改。初始化订阅时,只要挂起的更改仍可用于分发数据库,就会将它们传递至订阅服务器。

    • 与从备份中初始化不同,如果使用“仅支持复制”选项初始化订阅,则您或您的应用程序就必须确保在添加订阅时正确同步数据和架构。例如,如果从将数据和架构复制到订阅服务器到添加订阅这一时间段内,发布服务器上进行了某一活动,则此活动导致的更改可能不会复制到订阅服务器。

    有关详细信息,请参阅初始化事务订阅(不使用快照)

  • 对事务发布的存储过程执行的复制会在订阅服务器上产生不同的结果。

    如果复制存储过程的执行,则在初始化订阅时,会将过程定义复制到订阅服务器;当在发布服务器上执行该过程时,复制将在订阅服务器上执行相应的过程。有关详细信息,请参阅在事务复制中发布存储过程执行

    如果存储过程在订阅服务器上执行的操作或作用的数据与发布服务器上的不同,则可能会产生非收敛性。请考虑使用执行计算的过程,然后基于此计算插入数据。如果对订阅服务器进行了筛选,导致订阅服务器上的计算基于不同的数据,则在订阅服务器上插入的结果可能不同,也可能根本就不插入数据。

  • 事务项目使用的 INSERT 存储过程中包含一个未满足的条件。

    默认情况下,事务复制用一组存储过程将更改传播至订阅服务器。您也可以自定义这些过程,以将您的应用程序所需的业务逻辑包括在内。有关详细信息,请参阅指定如何传播事务性项目的更改。如果 INSERT 存储过程在它的逻辑中包含一个未满足的条件,则不进行插入。假设有一个定制的存储过程先检查订阅服务器上某个表(表 A)中的特定值,然后才允许插入到另一表(表 B)。如果由于错误或由于数据未复制到表 A 而导致表 A 中没有该值,那么表 B 中就会缺少这个本该有的行。

  • 数据被用户、复制脚本或其他应用程序删除:

    • 如果您希望允许用户在订阅服务器上删除数据,请使用合并复制、具有可更新订阅的事务复制或对等事务复制。删除会传播到发布服务器,所以,发布服务器和订阅服务器上的数据最终会收敛。有关详细信息,请参阅合并复制概述事务复制的发布类型

    • 如果希望防止用户在订阅服务器上删除数据,请为每个包含 ROLLBACK 词语并使用 NOT FOR REPLICATION 选项(此选项阻止触发器在复制代理执行操作时触发)的表创建一个触发器。例如:

      USE AdventureWorks2008R2;
      GO
      CREATE TRIGGER prevent_user_dml
      ON Person.Address
      FOR INSERT, UPDATE, DELETE
      NOT FOR REPLICATION
      AS
      ROLLBACK;
      

      有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)使用 NOT FOR REPLICATION 来控制约束、标识和触发器

    • 复制允许您在应用快照前后以及在同步期间执行脚本。使用 sp_addpublicationsp_addmergepublication@pre_snapshot_script@post_snapshot_script 参数,可以指定在应用快照之前和之后运行的脚本。有关详细信息,请参阅在应用快照之前和之后执行脚本。使用存储过程 sp_addscriptexec,您可以在同步过程中执行脚本。有关详细信息,请参阅如何在同步期间执行脚本(复制 Transact-SQL 编程)

      这些脚本通常用于管理任务。例如,在订阅服务器上添加登录名。如果用脚本来删除本应属于只读订阅服务器的数据,则管理员必须确保不会造成非收敛性。

  • 数据正由触发器删除,或者触发器包含 ROLLBACK 语句。

    必须正确管理订阅服务器上的触发器,以便不会引起非收敛性问题或其他问题:

    • 如果使用合并复制、具有可更新订阅的事务复制、或对等事务复制,则触发器应只在订阅服务器上导致数据发生更改。有关详细信息,请参阅合并复制概述事务复制的发布类型

    • 在许多情况下,触发器应使用 NOT FOR REPLICATION 选项。如果触发器包括 ROLLBACK 语句,并且不使用 NOT FOR REPLICATION 选项,则可能不会把行复制到订阅服务器。

    • 对于事务复制,还要注意有关 XACT_ABORT 设置以及在触发器中使用 COMMIT 和 ROLLBACK 语句的其他事项。有关详细信息,请参阅事务复制的注意事项的“触发器”部分。

请参阅

概念