SQL Server 2005 事务复制无法发布包含索引创建的存储过程

Posted

技术标签:

【中文标题】SQL Server 2005 事务复制无法发布包含索引创建的存储过程【英文标题】:SQL Server 2005 Transactional Replication Fails to Publish Stored Procedure Containing an Index Create 【发布时间】:2011-08-05 00:27:21 【问题描述】:

我在 SQL Server 2005 Transactional Publication 中遇到了一个奇怪的问题。问题是这样的:如果发布包含的文章是包含创建索引语句的存储过程,则在尝试将存储过程的架构复制到订阅者时会引发错误。

这种行为很奇怪,因为即使create index语句被注释掉,它仍然会给出异常,并且只有将它完全删除才会起作用.

这是返回的确切错误:

尝试的命令:GRANT EXECUTE ON [dbo].[usp_Test] 到 [公司数据库访问]

(交易序号: 0x00000170000008B9000500000000, 命令 ID:5)

错误消息:找不到对象 'usp_Test',因为它不存在 或者你没有权限。 (来源:MSSQLServer,错误号: 15151) 获得帮助:http://help/15151 找不到对象“usp_Test”, 因为它不存在或者你存在 没有权限。 (资源: MSSQLServer,错误号:15151) 获取 求助:http://help/15151

错误是准确的,因为当我检查订阅者时,存储过程没有按预期创建......但这就是发布的目的......

另外,我可以在订阅者上手动创建存储过程,但是当我生成快照时,它删除现有的存储过程,然后仍然返回此错误消息。

这里是一个创建此问题的示例出版物。

存储过程:

USE [CompanyDatabase]
GO

CREATE PROCEDURE [dbo].[usp_Test]

AS

CREATE TABLE #TempTable(ID INT)
CREATE NONCLUSTERED INDEX [IX_TempTable] ON [dbo].[#TempTable](ID)
SELECT 'Test'
GO

GRANT EXECUTE ON [dbo].[usp_Test] TO [CompanyDatabase_access]
GO

发布脚本:

-- Adding the transactional publication
use [CompanyDatabase]
exec sp_addpublication 
    @publication = N'Replication Test', 
    @description = N'Publication of database ''CompanyDatabase''.', 
    @sync_method = N'concurrent', 
    @retention = 0, 
    @allow_push = N'true', 
    @allow_pull = N'true', 
    @allow_anonymous = N'false', 
    @enabled_for_internet = N'false', 
    @snapshot_in_defaultfolder = N'true', 
    @compress_snapshot = N'false', 
    @ftp_port = 21, 
    @ftp_login = N'anonymous', 
    @allow_subscription_copy = N'false', 
    @add_to_active_directory = N'false', 
    @repl_freq = N'continuous', 
    @status = N'active', @independent_agent = N'true', 
    @immediate_sync = N'false', 
    @allow_sync_tran = N'false', 
    @autogen_sync_procs = N'false', 
    @allow_queued_tran = N'false', 
    @allow_dts = N'false', 
    @replicate_ddl = 1, 
    @allow_initialize_from_backup = N'false', 
    @enabled_for_p2p = N'false', 
    @enabled_for_het_sub = N'false'
GO

-- Adding the transactional articles
use [CompanyDatabase]
exec sp_addarticle 
    @publication = N'Replication Test', 
    @article = N'usp_Test', 
    @source_owner = N'dbo', 
    @source_object = N'usp_Test', 
    @type = N'proc schema only', 
    @description = N'', 
    @creation_script = N'', 
    @pre_creation_cmd = N'drop', 
    @schema_option = 0x0000000048000001, 
    @destination_table = N'usp_Test', 
    @destination_owner = N'dbo', 
    @status = 16
GO

-- Adding the transactional subscriptions
use [CompanyDatabase]
exec sp_addsubscription 
    @publication = N'Replication Test', 
    @subscriber = N'OtherDatabaseServer', 
    @destination_db = N'CompanyDatabase', 
    @subscription_type = N'Pull', 
    @sync_type = N'automatic', 
    @article = N'all', 
    @update_mode = N'read only', 
    @subscriber_type = 0
GO

订阅脚本:

/****** Begin: Script to be run at Subscriber ******/
use [CompanyDatabase]
exec sp_addpullsubscription 
    @publisher = N'DatabaseServer', 
    @publication = N'Replication Test', 
    @publisher_db = N'CompanyDatabase', 
    @independent_agent = N'True', 
    @subscription_type = N'pull', 
    @description = N'', 
    @update_mode = N'read only', 
    @immediate_sync = 0

exec sp_addpullsubscription_agent 
    @publisher = N'DatabaseServer', 
    @publisher_db = N'CompanyDatabase', 
    @publication = N'Replication Test', 
    @distributor = N'DatabaseServer', 
    @distributor_security_mode = 1, 
    @distributor_login = N'', 
    @distributor_password = N'', 
    @enabled_for_syncmgr = N'False', 
    @frequency_type = 64, 
    @frequency_interval = 0, 
    @frequency_relative_interval = 0, 
    @frequency_recurrence_factor = 0, 
    @frequency_subday = 0, 
    @frequency_subday_interval = 0, 
    @active_start_time_of_day = 0, 
    @active_end_time_of_day = 235959, 
    @active_start_date = 0, 
    @active_end_date = 0, 
    @alt_snapshot_folder = N'', 
    @working_directory = N'', 
    @use_ftp = N'False', 
    @job_login = null, 
    @job_password = null, 
    @publication_type = 0
GO
/****** End: Script to be run at Subscriber ******/

同样,奇怪的是,如果 create index 语句被注释掉,发布仍然会包含相同的错误,但如果完全删除它就会起作用。

目前,我刚刚从发布中删除了所有包含这些创建索引语句的存储过程,但我希望将它们复制到订阅者,以便对过程的任何 DDL 更新都会自动反映在订阅者上.

-- 编辑--

查看快照目录,usp_Test 的 .sch 文件包含与我之前为存储过程发布的完全相同的代码块...根据返回的错误,似乎快照代理决定不运行 CREATE PROCEDURE如果它包含创建索引,则继续执行并尝试运行 GRANT EXECUTE 命令,这会导致错误。

另外,我的 SQL Server 的确切版本是:

Microsoft SQL Server 2005 - 9.00.5254.00(2005 + SP4 累积更新 1)

-- 结束编辑--

我的问题是,为什么会这样?我的发布或订阅的配置是否存在问题?像其他人经历过这样的事情吗?我应该从哪里着手解决这个问题?

-- 更新--

我一直在 technet 上与 Hilary Cotter 交谈……但仍然没有运气。如果我删除该过程的 GRANT EXECUTE 权限,那么它会使用 CREATE INDEX 成功创建。所以它将与 GRANT EXECUTE OR CREATE INDEX 一起使用,但不能同时使用。 Hilary 建议可能是我的域中的某种类型的垃圾邮件设备在包含这两个关键字时阻止正确传输快照,但是如果我手动将 .sch 文件复制到订阅者并验证它是否包含预期的命令,我仍然遇到同样的问题。

【问题讨论】:

【参考方案1】:

嗯...没有什么对我跳出来的。出于好奇,快照 .sch 文件中有什么?这就是订阅者的快照代理运行的内容。

【讨论】:

好主意...我检查了 .sch 文件,并用结果更新了问题。 我无法解释您所看到的行为。您只在 sp_addarticle 的 @schema_option 参数中设置了 0x01。我建议您在订阅者处手动创建 proc 并将 @pre_creation_cmd 设置为“none”,以便在运行快照时它不会删除 proc。这应该能让你继续前进。【参考方案2】:

使用以下代码:快照中的存储过程将无法应用:

CREATE NONCLUSTERED INDEX [IX_TempTable] ON [dbo].[#TempTable](ID)

但是,稍微改变语法会导致创建存储过程没有问题:

ALTER TABLE dbo.#TempTable ADD CONSTRAINT IX_TempTable UNIQUE NONCLUSTERED ( ID )

我无法解释它,并且在这个故障上花费了数小时之后,我已经准备好停止寻找解释并接受这个解决方法。

【讨论】:

以上是关于SQL Server 2005 事务复制无法发布包含索引创建的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2005 - 无法回滚嵌套事务

SQL Server 2005,缩小复制数据库

SQL 2005 事务复制:快照处理期间的行为?

在Sql2000 sql2005 sql2008 下已能实现事务复制的强制订阅,但请求订阅始终不能实现总有下列错误提示

如何查看 SQL Server 2005 事务日志文件

sql server 2005 安装报错