首页 > 解决方案 > 带有立即更新的事务复制 - 发布者触发器在立即更新时触发,或者不复制它们的修改

问题描述

我有一个发布者和多个订阅者配置为即时更新的事务复制。我有两个复制表,MyTable 和 MyTableHistory。我有一个“不用于复制”触发器,它捕获对 MyTable 的更改历史并将它们放在 MyTableHistory 表中。这是我的问题:

如果我尝试仅在发布者上放置触发器: 当用户在订阅者上更新 MyTable 时,会立即通过分布式事务和 Microsoft 的存储过程在发布者上创建记录,并按照“立即更新”类型复制的预期触发。这会触发发布者上的触发器,该触发器会按预期在发布者上创建历史记录。但是,触发器刚刚创建的历史记录不会复制回订阅者。我猜这是他们阻止将已经复制的记录复制回发起它们的订户的副作用。

如果我尝试将触发器放在发布者和订阅者上: 当用户更新订阅者上的 MyTable 时,会立即在发布者上创建记录,该发布者触发触发器并导致重复的历史记录。无论我尝试了什么,我都无法弄清楚如何让触发器检测到记录正在被复制的“立即更新”修改,因此它应该中止。我试过“不用于复制”和“sp_check_for_sync_trigger”,但我了解到这些并不是为了检测我正在寻找的东西。

我认为上述两个选项中的第一个是首选,但在这一点上,我对任何可以使上述两个选项之一起作用的方法持开放态度。有任何想法吗?谢谢!

标签: sql-server

解决方案


我找到的最佳解决方案是将触发器放在发布者和订阅者上,并在触发器中包含以下代码以在某些条件下保释,以避免在复制维护期间触发触发器。它需要以下三种方法:

  1. 不适用于复制触发器选项 - 防止在将记录从发布者复制到订阅者时触发订阅者触发器
  2. spGetLastCommand - 这是我使用查看服务器状态权限创建的签名存储过程。它返回最后一个命令,因此我们可以检查它是否是在发布者上运行的复制存储过程,这样我们就可以防止发布者触发器在订阅者更改导致发布者立即更新时触发。
  3. sp_check_for_sync_trigger - 此代码可防止在复制存储过程尝试更新 ms_repl_tran 列时发出更新语句时触发触发器。

希望对某人有所帮助。但可能不是,因为我们是地球上最后一个使用这种复制的人;)

declare @last_command nvarchar(512)
exec master..spGetLastCommand @last_command output
if @last_command like '%sp_MSsync_%_MyTable_1%' begin
    return
end

declare @table_id int = object_id('MyTable')
declare @trigger_op varchar(max)
declare @retcode int
exec @retcode = sp_check_for_sync_trigger @table_id, @trigger_op output, @fonpublisher=1
if @retcode = 1 begin
    return
end
exec @retcode = sp_check_for_sync_trigger @table_id, @trigger_op output, @fonpublisher=0
if @retcode = 1 begin
    return
end";

推荐阅读