将文章添加到事务发布中,而不会生成新快照


23

将SQL 2008 R2事务复制与请求订阅者一起使用时,添加文章时,我希望避免创建整个快照(数据库约为80 GB,因此需要花费数小时)。

本文开始,我已经了解了如何通过关闭Instant_sync来使用部分快照来执行此操作,但这对我们不起作用。

理想情况下,我想将其作为数据库脚本的一部分来运行以创建表,因此,如果要复制它,可以这样做:

Create Table ...    
sp_addArticle ...    
sp_PushThisToOurSubscribersNow    

Answers:


13

您可以使用GUI通过SSMS添加文章,甚至对其应用过滤器。只要您不更改文章的任何其他属性,就不需要生成完整的快照。

当您在发布GUI中单击OK(添加文章后)时,它将关闭而不提示重新初始化-如果确实提示重新初始化,则您已更改了需要FULL快照的内容。如果发生这种情况,请点击“ 取消”,然后重试。

添加文章后,您可以简单地启动快照作业,并且您会注意到它仅为新文章生成快照(称为迷你快照)。

然后检查您的分发作业,并注意它在订户上创建了表并批量复制了您的数据。

祝您好运,如果您需要进一步的帮助,请告诉我。


我做了这个答案中解释的所有事情,但仍然发现自己在等待整个复制的数据库进行同步。添加新文章后,没有提示我重新初始化,但是仍然进行了完全初始化。小心。
JzInqXc9Dg

7
  1. 在发布属性窗口中添加新文章(取消选中列表中仅显示选中的文章)
  2. 右键单击同一发布节点,然后转到“ 查看快照代理状态
  3. 单击“ 开始”,然后在同一窗口中记录日志,该日志显示仅同步了此新文章
  4. 不久后,新文章将在订阅者中同步,而无需初始化所有先前同步的

在此处输入图片说明


3

我有一个同样的问题,即使我已经有一段时间了,但是我对复制的了解还不够深,无法完全满意,所以我认为以下资源和指南对您有所帮助:

  • 这个博客提供了一个很好的过程概述。它还提醒我们,如果您的出版物很大,并且将其选项设置为“ immediate_sync”,则每次添加或更改文章时,都会准备一个全新的快照。因此,他有一个方便的技巧来更改该选项,方法是使用sp_changePublication @publication='MyPub', @property='immediate_sync', @value='false';

  • MSDN博客文章 “ repltalk”(听起来像是一个很好的资源!)-与“直接”无关,但仍然有帮助

  • 这个问题在@ Brandon-Williams指出的地方,如果是Pull订阅,则还应该使用sp_refreshSubscriptions @publication = 'MyPub'

  • SSMS复制监视器-按照指南停止和启动代理(快照,日志读取器)的便捷方法。

这是我遵循的实际步骤,效果很好,并获得了我的主管DBA的批准:

  1. 打开复制监视器,选择发布,转到“代理”,右键单击“日志读取器代理”,再单击“停止”。
  2. 将发布设置为不允许匿名和不立即同步,请使用sp_changePublication-是,正如@cody_konior指出的那样,该文档的文档不足,但是在我的情况下确实可以正常工作。青年汽车
  3. 使用脚本在订阅服务器上手动创建表,并使用链接服务器查询填充数据(因为它很小)。您也可以使用SSIS,BCP或其他一些方法来执行此操作。如果您对repl-snapshot没问题,可以这样做,但可能没有必要。我只是想在第一时间手动进行准备。
  4. 使用添加文章(表格) sp_addArticle
  5. 使用以下方式添加表格的所有列sp_articleColumn(指定的出版物和文章,请勿指定列->表示所有列)
  6. 为该sp_refreshSubscriptions出版物执行以刷新下拉菜单
  7. 再次打开Replication Monitor,选择发布,转到Agent,右键单击Snapshot Agent,单击“启动”。它将运行一次,创建新的快照。
  8. 右键单击Log Reader Agent,单击“开始”。它会启动并继续正常运行,并且您的复制现在应该可以再次工作了。

是的,您可以使用SSMS GUI进行大多数更改,但我发现将所有内容全部编写为脚本很有帮助,因此它可以是A)在源代码控制(更改控制)下,并且B)重复部署或部署到多个实例。不幸的是,我没有花时间来编写代理停止/启动的脚本,但是考虑到它们只是SQL Agent Jobs,这应该不难。您只需要完成整个“使用Job-Name查找JobID”招(查询sysjobs-真的,是MS?)...

希望对以后的读者有所帮助!


3

如在向现有出版物添加文章和从现有出版物中删除文章中所述,您必须*为出版物创建新的快照。

为了避免增加新的文章的时候生成快照的所有文章,发布属性immediate_sync必须设置为0。呼叫sp_addarticle,然后sp_addsubscription。如果订阅取消,您还必须致电sp_refreshsubscriptions。然后生成快照,并且只会为新添加的文章生成快照。

*这是SQL Server联机丛书中推荐的方法。您的方法存在的问题是它容易出错。


2

重大修改 这是对该答案的完整重写(对以前的版本容易出错并且会引起问题的观点提出了有效的批评)。

还发布了有关如何将其应用于的演示:Youtube-SQL Server复制:如何添加文章而无需创建快照

重要提示:这是不是微软的推荐的方法,所以你会在你自己与问候得到它的工作,也不要没有显著隔离测试直接应用到您的生产环境和让自己舒服的步骤!

遵循的步骤:

Planning steps:
    * Choose Publication that article will be added to
    * Gather information about the publication 
        exec sp_helppublication '[Name of Publication]'
        https://msdn.microsoft.com/en-us/library/ms189782(v=sql.105).aspx
        - replication frequency = 0 - this is Transactional replication (THIS IS A REQUIREMENT FOR THIS METHOD)
        - replicate_ddl = 1 - means ALTER TABLES will apply SQL Server generated repl procs
        - independent_agent = 1 - means that you will only affect tables in this publication when deploying
    * Identify which subscribers are going to be affected

Pre-deployment steps (can be done at any time)
    1. Create table on subscribers
    2. Create custom replication procs on subscribers
       (Customisation will ignore if the IUD has already been applied to subscriber - because you have manually sync'd the data)

Deployment/Potential impact:
    3. Stop Distribution Agents to all subscribers for this publication
    4. Add article to publication on publisher
    5. Sync data from publisher to subscriber
    6. Start Distribution Agents to all subscribers for this publication
    7. Monitor/Verify all data has arrived

Optional follow on:
    8. Apply standard repl procs (removing if not exists checks)
       This is optional as the generated repl scripts should be fine for the most part

Note:  When ALTER table scripts are applied on the Publisher (when replicate_ddl = 1) repl procs will automatically be recreated by the Distribution Agent (so any customisation will be lost)

验证:

  • 在发布者上执行插入-验证行到达订阅者
  • 在发布者上执行更新-确认更改已到达订阅者
  • 在发布者上执行删除-验证在订阅者上删除的行
  • 验证最后n行已到达并在发布者和订阅者之间匹配

示例流程

A)在发布者上创建一个表:

/* Deliberately applying IDENTITY, DEFAULT & INDEX to demonstrate usage on subscriber */
CREATE TABLE [dbo].[TableNotUsingSnap](
    [Id] [int] NOT NULL IDENTITY(1,1),
    [Note_Text] [varchar](4096) NOT NULL,
    [CreatedDate] [datetime] NULL,
    [LoggedDate] [datetime] NOT NULL CONSTRAINT DF_TableNotUsingSnap_LoggedDate DEFAUlT GETUTCDATE(),
 CONSTRAINT [PK_TableNotUsingSnap] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO 

CREATE NONCLUSTERED INDEX [IDX_NC_TableNotUsingSnap_LoggedDate]  ON [dbo].[TableNotUsingSnap]
(
    [LoggedDate] ASC
) INCLUDE ([Note_Text])
GO

B)创建一个作业/进程/脚本来对[TableNotUsingSnap]进行一些插入/更新/删除(然后,您可以使用此方法来验证如何使用此方法正确同步订阅者。

预备步骤:

1.在订阅服务器上创建表

/* example script to add a table to a publication without running the snapshot agent 
Steps: 
    Pre steps: 
    1. Create table on subscribers
    2. Create replication procs on subscribers

    Deployment/Potential impact:
    3. Stop Distribution Agents to all subscribers for this publication
    4. Add article to publication on publisher
    5. DTS data from publisher to subscriber
    6. Start Distribution Agents to all subscribers for this publication
    7. Monitor/Verify all data has arrived

=========================================================
Notes:
    * Drop unnecessary FK's, Indexes
    * Do NOT have IDENTITY(1,1), DEFAULTS
    * Do have a Clustered PK
    * Create appropriate indexes for your subscribers use case */ 

-- RUN ON SUBSCRIBER
IF OBJECT_ID('dbo.TableNotUsingSnap') IS NOT NULL
    exec sp_rename 'dbo.TableNotUsingSnap', 'TableNotUsingSnap_20170127'
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TableNotUsingSnap](
    [Id] [int] NOT NULL,
    [Note_Text] [varchar](4096) NOT NULL,
    [CreatedDate] [datetime] NULL,
    [LoggedDate] [datetime] NOT NULL,
 CONSTRAINT [PK_TableNotUsingSnap] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

2.在订阅服务器上创建复制存储过程(更新/插入/删除)

您可以创建repl proc:

  • 手动(请小心,因为很容易出错!)
  • 在开发人员机器上使用MS Snapshot方法添加文章,并在repl procs上编写脚本(准备好进行调整)
  • 创建/查找某种生成器

您需要应用的更改:

  • sp_MSins_ [Schema] [TableName]- IF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1)如果已经存在,则添加为不插入
  • sp_MSupd_ [Schema] [TableName]-注释掉IF @@rowcount = 0 ... exec sp_MSreplraiserror ...以忽略未应用的更新(因为在同步数据之前,记录可能已在发布者上删除了)
  • sp_MSdel_ [Schema] [TableName]-注释掉IF @@rowcount = 0 ... exec sp_MSreplraiserror ...以忽略不应用的删除(因为在同步数据之前,该记录可能已在发布者上删除了)

sp_MSins_dboTableNotUsingSnap:

/* Customised Replication insert proc utilized to support adding to replication without a snapshot. */
create procedure [dbo].[sp_MSins_dboTableNotUsingSnap]     
    @c1 int,     
    @c2 varchar(4096),     
    @c3 datetime
AS 
BEGIN
    IF NOT EXISTS (SELECT 'row already exists' FROM [dbo].[TableNotUsingSnap] dest WITH (NOLOCK) WHERE dest.Id = @c1)
    BEGIN
        insert into [dbo].[TableNotUsingSnap]
            ([Id],
            [Note_Text],
            [Repl_Upsert_UTC]) 
        values 
            (@c1,
            @c2,
            @c3)  
    END
END
GO

sp_MSupd_dboTableNotUsingSnap:

/* Customised Replication insert proc utilized to support adding to replication without a snapshot. */
create procedure [dbo].[sp_MSupd_dboTableNotUsingSnap]     
    @c1 int = NULL,     
    @c2 varchar(4096) = NULL,     
    @c3 datetime = NULL, 
    @pkc1 int = NULL, 
    @bitmap binary(1)
AS 
BEGIN
    declare @primarykey_text nvarchar(100) = '' 

    if (substring(@bitmap,1,1) & 1 = 1)
    begin 
        update [dbo].[TableNotUsingSnap]
        set [Id] = case substring(@bitmap,1,1) & 1 when 1 then @c1 else [Id] end, 
            [Note_Text] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [Note_Text] end,
            [Repl_Upsert_UTC] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Repl_Upsert_UTC] END
        WHERE [Id] = @pkc1

        /*  Commented out while adding to publication
        if @@rowcount = 0
            if @@microsoftversion>0x07320000
            Begin
                set @primarykey_text = @primarykey_text + '[id] = ' + convert(nvarchar(100),@pkc1,1)
                exec sp_MSreplraiserror @errorid=20598, @param1=N'[dbo].[TableNotUsingSnap]', @param2=@primarykey_text, @param3=13233
            End */
    END
    ELSE
    BEGIN
        update [dbo].[TableNotUsingSnap]
        set [Note_Text] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [Note_Text] end,
            [Repl_Upsert_UTC] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Repl_Upsert_UTC] END
        WHERE [Id] = @pkc1

        /*  Commented out while adding to publication
        if @@rowcount = 0
            if @@microsoftversion>0x07320000
            Begin
                set @primarykey_text = @primarykey_text + '[id] = ' + convert(nvarchar(100),@pkc1,1)
                exec sp_MSreplraiserror @errorid=20598, @param1=N'[dbo].[TableNotUsingSnap]', @param2=@primarykey_text, @param3=13233
            End */
    end
END
GO

sp_MSdel_dboTableNotUsingSnap:

/* Customised Replication insert proc utilized to support adding to replication without a snapshot. */
create procedure [dbo].[sp_MSdel_dboTableNotUsingSnap]
    @pkc1 int
as
begin  
    declare @primarykey_text nvarchar(100) = ''

    delete [dbo].[TableNotUsingSnap]
    where [Id] = @pkc1

    /* ignore if the record doesn't exist when deleting it 
    if @@rowcount = 0
        if @@microsoftversion>0x07320000
        Begin
            set @primarykey_text = @primarykey_text + '[Id] = ' + convert(nvarchar(100),@pkc1,1)
            exec sp_MSreplraiserror @errorid=20598, @param1=N'[dbo].[TableNotUsingSnap]', @param2=@primarykey_text, @param3=13234
        End */
end
GO

部署步骤

3.停止分发代理-在分发服务器(推)或订户(拉)上

/*  example script to add a table to a publication without running the snapshot agent
    Steps:
        Pre steps:
        1. Create table on subscribers
        2. Create replication procs on subscribers

        Deployment/Potential impact:
    **  3. Stop Distribution Agents to all subscribers for this publication
        4. Add article to publication on publisher
        5. DTS data from publisher to subscriber
        6. Start Distribution Agents to all subscribers for this publication
        7. Monitor/Verify all data has arrived

    =========================================================
    Note: check your publication settings:
          if @independent_agent = N'false'
            you will need to stop the distribution agent which will affect ALL
            publications going to that subscriber

          if @independent_agent = N'true'
            you will need to stop the publication specific distribution agent 
            (to each subscriber)

          Plan your live release around that knowledge!
*/

-- IF PUSH REPLICATION: RUN ON DISTRIBUTION SERVER
-- IF PULL REPLICATION: RUN ON SUBSCRIBER SERVER

/* disable the Job first */
exec msdb..sp_update_job @job_name = '[Distribution agent job]', @enabled = 0
GO

/* wait for 10 seconds - precaution ONLY */
WAITFOR DELAY '00:00:10.000'
GO

/* now stop the job */
exec msdb..sp_stop_job @job_name = '[Distribution agent job]'
GO

/* 
    NOTE: You might recieve an error about stopping a job that is already stopped.  You can ignore that error.
                It is up to you to verify that the job has been stopped correctly!
*/

4.现在将文章添加到发布中-在发布者上

关键参数:

  • sp_addarticle- @pre_creation_cmd = N'none'用于告诉分发代理不要删除并生成自己的对象
  • sp_addsubscription- @sync_type = N'none'用来告诉Distributer不需要创建新快照,它可以将IUD命令排入队列

sp_addarticle:

exec sp_addarticle 
    @publication = N'Publication Name',
    @article = N'TableNotUsingSnap',
    @source_owner = N'dbo',
    @source_object = N'TableNotUsingSnap',
    @type = N'logbased',
    @description = N'',
    @creation_script = N'',
    @pre_creation_cmd = N'none',        /* this is a critical flag - tells SQL Server to not drop/recreate the repl procs/object on the subscriber */
    @schema_option = 0x0000000008004093,
    @identityrangemanagementoption = N'none',
    @destination_table = N'TableNotUsingSnap',
    @destination_owner = N'dbo',
    @status = 16,
    @vertical_partition = N'false',
    @ins_cmd = N'CALL [sp_MSins_dboTableNotUsingSnap]',
    @del_cmd = N'CALL [sp_MSdel_dboTableNotUsingSnap]',
    @upd_cmd = N'SCALL [sp_MSupd_dboTableNotUsingSnap]'
GO

-- Adding the transactional subscriptions
exec sp_addsubscription @publication = N'Publication Name',
    @subscriber = N'Subscriber Server',
    @destination_db = N'Subscriber DB',
    @subscription_type = N'Push',
    @sync_type = N'none',               /* tell SQL Server not to sync/snapshot this change to the publication */
    @article = N'all',
    @update_mode = N'read only',
    @subscriber_type = 0
GO

5.同步数据

现在,您需要将数据复制到订户中,您可以:

  • 创建链接的服务器并复制到整个服务器
  • 使用导出/导入向导
  • 还原备份并应用差异
  • 使用SSMS工具包“生成插入语句...”提取表

您使用的确切方法取决于读者,这还取决于您愿意停止分发代理多长时间。

额外:作为测试中的附加步骤,这里是运行脚本(从步骤(B)开始)以在[TableNotUsingSnap]上创建IUD操作的好地方,以便您对这种方法有信心。

6.重新启动分发代理-在分发服务器(推)或订户(拉)上

/*  example script to add a table to a publication without running the snapshot agent
    Steps:
        Pre steps:
        1. Create table on subscribers
        2. Create replication procs on subscribers

        Deployment/Potential impact:
        3. Stop Distribution Agents to all subscribers for this publication
        4. Add article to publication on publisher
        5. DTS data from publisher to subscriber
    **  6. Start Distribution Agents to all subscribers for this publication
        7. Monitor/Verify all data has arrived

    =========================================================
    Note: check your publication settings:
          if @independent_agent = N'false'
            you will need to stop the distribution agent which will affect ALL
            publications going to that subscriber

          if @independent_agent = N'true'
            you will need to stop the publication specific distribution agent 
            (to each subscriber)

          Plan your live release around that knowledge!
*/

-- IF PUSH REPLICATION: RUN ON DISTRIBUTION SERVER
-- IF PULL REPLICATION: RUN ON SUBSCRIBER SERVER

/* disable the Job first */
exec msdb..sp_update_job @job_name = 'Distribution agent job', @enabled = 1
GO

/* wait for 10 seconds - precaution ONLY */
WAITFOR DELAY '00:00:10.000'
GO

/* now stop the job */
exec msdb..sp_start_job @job_name = 'Distribution agent job'
GO

/* 
    Now go and make sure everything is working ok!
*/
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.