【问题标题】:sp_replmonitorhelppublisher - "An INSERT EXEC statement cannot be nested."sp_replmonitorhelppublisher - “不能嵌套 INSERT EXEC 语句。”
【发布时间】:2014-07-07 21:56:31
【问题描述】:

问题

我在 Microsoft SQL Server 2008 上收到此错误:

消息 8164,级别 16,状态 1,过程 sp_MSload_tmp_replication_status,第 80 行 不能嵌套 INSERT EXEC 语句。

背景

我正在尝试以编程方式监控 Microsoft SQL Server 中的复制状态。我在 sp_replmonitorhelppublisher 上使用 INSERT EXEC 语句来获取状态,接下来的问题不限于此 proc,但我提到它是因为 proc 是内置的,所以我无法重写它以“以应有的方式”获取数据。我获取数据的(简化)代码是:

declare @t table (
    publisher nvarchar(max) null,
    distribution_db nvarchar(max) null,
    status nvarchar(max) null,
    warning nvarchar(max) null,
    publicationcount nvarchar(max) null,
    returnstamp nvarchar(max) null
)
insert into @t exec sp_replmonitorhelppublisher 'MY_PUBLISHER'

问题

我了解导致错误的 MS SQL Server 限制,我猜在内置 proc 的某处有一些 INSERT EXEC 语句。我不明白的是:

  1. 为什么有时它可以正常工作而没有错误(我已经看到它成功运行了几次)?
  2. 为什么在实际的 INSERT EXEC 正常工作之前运行相同的 EXEC 语句(不是作为 INSERT EXEC 的一部分)的解决方法? IE。此代码工作正常:

    declare @t table (
        publisher nvarchar(max) null,
        distribution_db nvarchar(max) null,
        status nvarchar(max) null,
        warning nvarchar(max) null,
        publicationcount nvarchar(max) null,
        returnstamp nvarchar(max) null
    )
    exec sp_replmonitorhelppublisher 'MY_PUBLISHER' -- extra call before main call
    insert into @t exec sp_replmonitorhelppublisher 'MY_PUBLISHER'
    
  3. 此解决方法是否保证运行时不会出现错误?为什么?

  4. 或者是否涉及某种形式的缓存,恰好对我有用,但不能保证每次调用都有效?
  5. 有没有更好的方式以编程方式监控复制?

【问题讨论】:

  • 如果您转到 Management Studio 树的系统存储过程节点,您可以阅读相关存储过程的源代码。我的猜测是在存储过程的某个地方,它使用insert...exec 命令缓存信息。如果您想创建自己的复制监控,那么您可以按照sp_replmonitorhelppublisher 中的代码进行修改,以满足您自己的要求。
  • 我试图遵循 proc 的代码,但似乎里面有一些魔法:sp_replmonitorhelppublisher 调用 distribution.sys.sp_replmonitorhelppublisherhelper,我在树中找不到。无论如何,非常有用的提示。谢谢,@podiluska。

标签: sql sql-server sql-server-2008 tsql stored-procedures


【解决方案1】:

我正在处理相同的问题 - 以编程方式监控复制状态。我发现执行sp_replmonitor* 存储过程也会更新表dbo.MSReplication_monitordata。此表保存复制的当前状态信息。

所以,我的解决方案是执行sp_replmonitorhelppublisher,然后从dbo.MSReplication_monitordata 中读取值。

例如:开始发布并等待它完成(在 SQL Server 代理作业中)是通过以下方式完成的:

USE [DB]
DECLARE @StartDateTime datetime = GETDATE()
EXEC sp_startpublication_snapshot @publication='publ_DB'

USE [distribution]
DECLARE @Status int = 1

WHILE @status NOT IN (2, 6)
BEGIN
    WAITFOR DELAY '00:00:05'
    EXEC sp_replmonitorhelppublisher
    SELECT @Status = status FROM dbo.MSReplication_monitordata WHERE publication='publ_DB' AND agent_type=1 AND time_stamp>@StartDateTime
END

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2013-05-17
    • 2016-05-02
    • 2017-10-18
    • 2019-11-12
    • 2020-01-21
    • 2018-03-20
    • 2012-04-24
    • 1970-01-01
    相关资源
    最近更新 更多