由于复制错误无法删除表,尽管表未发布

Mik*_*Fal 4 replication sql-server transactional-replication

我试图删除作为发布者的数据库中的表。有问题的表没有被发布。我得到的错误是:

Msg 15021, Level 16, State 1, Procedure sp_MStran_ddlrepl, Line 14 [Batch Start Line 1]
Invalid value given for parameter @procmapid. Specify a valid parameter value.
Msg 3609, Level 16, State 2, Line 2
The transaction ended in the trigger. The batch has been aborted.
Run Code Online (Sandbox Code Playgroud)

我已经检查sysarticles过是否有旧记录或孤立记录,但该表没有出现。关于这里的问题有什么想法吗?

编辑:SQL Server 2016 RTM

小智 7

TL;DR:如果您还原(或移动)先前复制到较低版本和/或补丁级别的服务器的数据库,然后重新启用复制,则会发生此错误。有关解决方案和更长的解释,请参见下文。

复制使用数据库触发器来处理某些事情

当为 SQL Server 中的事务复制发布数据库时,作为设置过程的一部分,将创建多个数据库级触发器。通常,它们是:

tr_MStran_alterschemaonly
tr_MStran_altertable
tr_MStran_altertrigger
tr_MStran_alterview
Run Code Online (Sandbox Code Playgroud)

您可以通过在对象资源管理器中扩展数据库,然后查看“可编程性”和“数据库触发器”来找到它们。他们几乎按照他们说的去做。如果您查看其中的代码,tr_MStran_altertable您会发现每次为 ALTER TABLE 语句触发此触发器时,SQL Server 都会使用 EventData() 函数来捕获正在更改的内容,然后调用另一个将实际捕获更改的复制存储过程活动并将相关的 DDL 事务发送到分发数据库。这与查找和捕获数据更改的日志读取器代理不同。

每次发布要复制的数据库时都会创建这些触发器,并且在删除复制过程中也会删除这些触发器。

SQL Server 2014 SP2 和 SQL Server 2016 SP1 中的新 DROP TABLE 支持

在 SQL Server 2014 SP2 和 SQL Server 2016 SP1 中,Microsoft 引入了 SQL Server 复制的更改:支持 DROP TABLE ( https://support.microsoft.com/en-us/help/3170123 )。以前,您无法删除标记为复制的表。这个默认情况下不启用的新功能意味着 DROP TABLE 语句将不再抛出错误。为促进此更改,添加了一个新的数据库级触发器:tr_MStran_droptable. 这是为每个删除表操作触发的触发器,它使用事件数据来确定哪个表被删除,以及是否启用了即使表被标记为复制也支持事务的选项。

但是“旧”版本的 SQL Server 呢?

这就是问题所在:这个触发器只能通过在支持它的版本上的复制来创建......并且只能通过在支持它的版本上的复制来删除。因此,即使您决定使用类似sp_removedbreplication此触发器的内容进行核复制,也不会删除,并且每次尝试删除表时都会继续触发,即使您尝试删除的表未标记为复制。在以下情况下可能会发生这种情况:

  1. 您在支持此功能的版本(2016 SP1 或 2014 SP2)上发布了用于复制的数据库
  2. 您将此数据库备份和还原到不支持此功能的 SQL Server 版本(如 2016 RTM 或 2014 SP1)
  3. 您发布还原的数据库以进行复制。

您可以自己测试:如果您禁用复制并重新启用它,您会注意到数据库触发器上的创建时间将与您重新启用发布时一致,但tr_MStran_droptable触发器仍然存在。

解决问题

要解决此问题,您可以:

  1. 将受影响的实例升级到支持此触发器的补丁级别(2014 SP2 或 2016 SP1)。
  2. 手动删除触发器,因为它不受支持。