是否可以仅在订阅者中更改表的主键(从非集群到集群)而不破坏复制?

Mar*_*lli 1 replication sql-server transactional-replication sql-server-2014 automation

我有一个表,它有一个聚集唯一索引和一个与索引结构相同的非聚集主键。

IF OBJECT_ID('[dbo].[tblBAccountHolder]') IS NOT NULL 
DROP TABLE [dbo].[tblBAccountHolder] 
GO
CREATE TABLE [dbo].[tblBAccountHolder] ( 
[lngParticipantID]  INT                              NOT NULL,
[sdtmCreated]       SMALLDATETIME                    NOT NULL,
[strUsername]       VARCHAR(20)                          NULL,
[strPassword]       VARCHAR(20)                          NULL,
[tsRowVersion]      TIMESTAMP                        NOT NULL,
CONSTRAINT   [PK_tblAccountHolder]  
PRIMARY KEY NONCLUSTERED ([lngParticipantID] asc),

CONSTRAINT   [IX_tblBAccountHolder__lngParticipantID]  
UNIQUE CLUSTERED    ([lngParticipantID] asc) 
WITH FILLFACTOR = 100)
Run Code Online (Sandbox Code Playgroud)

正如您在定义中看到的那样,只有一列:

 CREATE  UNIQUE CLUSTERED INDEX IX_tblBAccountHolder__lngParticipantID 
 ON [dbo].[tblBAccountHolder] (  [lngParticipantID] ASC  )  
Run Code Online (Sandbox Code Playgroud)

我想删除唯一索引,并更改主键以使其成为集群。我将保留相同的主键,只需将其从非集群更改为集群。

该表是事务复制的一部分,我只会在订阅者数据库上完成此操作。不在发布者中。

这是一个包含超过 9,293,193 行的表格。

我会搞砸复制吗?

问题是我必须删除主键约束并将其重新创建为集群。

这是我想在订阅者数据库中完成的操作:

drop INDEX IX_tblBAccountHolder__lngParticipantID 
        ON [dbo].[tblBAccountHolder]  
GO

ALTER TABLE [dbo].[tblBAccountHolder] 
       drop CONSTRAINT [PK_tblAccountHolder] 
GO

 ALTER TABLE [dbo].[tblBAccountHolder] 
   ADD  CONSTRAINT [PK_tblAccountHolder] 
 PRIMARY KEY CLUSTERED (  [lngParticipantID] ASC  )  
  WITH (  PAD_INDEX = OFF,
          FILLFACTOR = 95,
          SORT_IN_TEMPDB = OFF , IGNORE_DUP_KEY = OFF , 
          STATISTICS_NORECOMPUTE = OFF , ONLINE = ON , 
          ALLOW_ROW_LOCKS = ON , ALLOW_PAGE_LOCKS = ON  ) ON [PRIMARY ] 
GO
Run Code Online (Sandbox Code Playgroud)

Mar*_*lli 6

不,这是不可能的。

当表参与复制时,它不允许您删除主键。

下面是我如何更改复制表的主键的示例:

表是dbo.CategoryImportMap,数据库是Product_Staging

---------------------------------------------------------------------------------------------------
-- remove the table from the replication
---------------------------------------------------------------------------------------------------

USE [Product_Staging]
GO
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

exec sp_dropsubscription @publication = N'Product_Staging', @article = N'CategoryImportMap', @subscriber = N'all', @destination_db = N'all'
GO
exec sp_droparticle @publication = N'Product_Staging',      @article = N'CategoryImportMap', @force_invalidate_snapshot = 0
GO

---------------------------------------------------------------------------------------------------
-- do the schema changes
---------------------------------------------------------------------------------------------------

BEGIN TRANSACTION;

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;


SELECT @@TRANCOUNT


ALTER TABLE [dbo].[CategoryImportMap]
 DROP CONSTRAINT [PK_CategoryImportMap] 

DROP index [UC_SegmentCategory]
on  [dbo].[CategoryImportMap]

ALTER TABLE [dbo].[CategoryImportMap]
ADD CONSTRAINT   [PK_CategoryImportMap]  PRIMARY KEY CLUSTERED   (  [MPlanSegmentCode] ASC  , [MPlanCategoryCode] ASC  )



SELECT @@TRANCOUNT

COMMIT TRANSACTION


---------------------------------------------------------------------------------------------------
-- add the table back to the replication
---------------------------------------------------------------------------------------------------

SET TRANSACTION ISOLATION LEVEL read committed;

EXEC sp_addarticle @publication = N'Product_Staging', 
                   @article = N'CategoryImportMap',
                   @source_object=N'CategoryImportMap',
                   @destination_table =N'CategoryImportMap'
GO

--========================================================================
-- REFRESH THE SUBSCRIPTIONS
--========================================================================
EXEC sp_refreshsubscriptions @publication = N'Product_Staging'
GO

--========================================================================
-- Start the Snapshot Agent job.
--========================================================================
EXEC sp_startpublication_snapshot @publication = N'Product_Staging'
go


-- test number of rows (source and destination)
sp_count 'CategoryImportMap'
Run Code Online (Sandbox Code Playgroud)


小智 5

在开始部署Marcello 的脚本之前添加以下检查:

确保将immediate_syncallow_anonymous设置FALSE (0)为避免创建完整快照而不仅仅是更改的文章的快照。

SELECT immediate_sync, allow_anonymous 
FROM Your_Published_DBName.dbo.syspublications
Run Code Online (Sandbox Code Playgroud)

如果这些值未设置,FALSE您可以使用以下命令更改它们:

EXEC sp_changepublication
@publication = 'reDBA',
@property = N'allow_anonymous',
@value = 'false'
Run Code Online (Sandbox Code Playgroud)

禁用后,immediate_sync事务一旦复制到订阅者就会被删除。除非有特定的业务需要添加新订阅者或重新初始化现有订阅者,否则禁用通常是安全的。

EXEC sp_changepublication
@publication = 'reDBA',
@property = N'immediate_sync',
@value = 'false'
Run Code Online (Sandbox Code Playgroud)

经过这些简单的检查后,您可以继续使用 Marcello 的脚本,从而节省大量时间、麻烦和停机时间。