web-dev-qa-db-ja.com

新しいスナップショットを生成せずにトランザクションパブリケーションに記事を追加する

プルサブスクライバーでSQL 2008 R2トランザクションレプリケーションを使用して、記事を追加するときに、スナップショット全体を作成する必要がないようにします(dbは〜80 GBなので、これには数時間かかります)。

この記事 から、immediate_syncをオフに設定して部分的なスナップショットを使用してこれを行う方法を確認しましたが、それはうまくいきませんでした。

理想的には、テーブルを作成するdbスクリプトの一部としてこれを実行したいので、複製したい場合は、次のようにします。

Create Table ...    
sp_addArticle ...    
sp_PushThisToOurSubscribersNow    
24
user175528

GUIを使用してSSMSから記事を追加し、フィルターを適用することもできます。記事の他のプロパティを変更しない限り、完全なスナップショットを生成する必要はありません。

(記事を追加した後)パブリケーションGUIで[OK]をクリックすると、再初期化を求めるプロンプトが表示されずに閉じます-もしそれがdoes再初期化を促す場合、フルスナップショットを必要とする何かを変更しました。その場合は、キャンセルを押して再試行してください。

記事を追加した後、スナップショットジョブを開始するだけで、新しい記事のスナップショット(ミニスナップショットと呼ばれる)のみが生成されることがわかります。

次に、配布ジョブを確認すると、サブスクライバーでテーブルが作成され、データが一括コピーされていることがわかります。

幸運を祈ります。さらにサポートが必要な場合はお知らせください。

13
NTDLS
  1. パブリケーションに新しい記事を追加プロパティウィンドウ(リスト内のチェックされた記事のみを表示のチェックを外します)
  2. 同じPublicationノードを右クリックし、「View Snapshot Agent Status」に移動します
  3. startをクリックし、この新しい記事が同期されているだけであることを示す同じウィンドウのログに注意してください
  4. しばらくすると、以前に同期されたものをすべて初期化せずに、新しい記事がサブスクライバーで同期されます。

enter image description here

8
Iman Abidi

私も同じ質問をしましたが、しばらくDBAを使用していましたが、完全に満足できるほど深くレプリケーションを扱っていなかったので、次のリソースとガイドが役立つと思いました。

  • このブログ 、プロセスの概要を説明しました。また、既存の大きなパブリケーションがあり、そのオプションが "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を使用して、パブリケーションを許可-匿名および即時同期しないように設定します-はい。 YMMV
  3. (小さいため)リンクサーバークエリを使用してデータを入力し、スクリプトを使用してサブスクライバーで手動でテーブルを作成しました。 SSIS、BCP、またはその他の方法でこれを行うこともできます。そして、repl-snapshotがそれをやってくれれば、それは必要ないかもしれません。初めて手動で準備したかっただけです。
  4. sp_addArticleを使用して記事(表)を追加します
  5. sp_articleColumnを使用してテーブルのすべての列を追加します(指定された出版物と記事、DIDNは列を指定しない->すべての列を意味します)
  6. そのパブリケーションに対してsp_refreshSubscriptionsを実行して、プーラーを更新します
  7. レプリケーションモニターを再度開き、パブを選択して、[エージェント]に移動し、[スナップショットエージェント]を右クリックして、[開始]をクリックします。一度実行され、新しいスナップショットが作成されます。
  8. [ログリーダーエージェント]を右クリックし、[開始]をクリックします。起動して通常どおり実行を継続し、レプリケーションが再び機能するようになります。

そして、はい、あなたはSSMS GUIでほとんどの変更を行うことができましたすべてをスクリプト化して、A)ソース管理(change-コントロール)、およびB)繰り返しまたは複数のインスタンスに展開されます。残念ながら、エージェントの停止/開始のスクリプトを作成するために時間を費やしませんでしたが、SQLエージェントジョブのみであることを考えると、それほど難しくありません。 「Job-Nameを使用してJobIDを見つける」トリック全体を実行する必要があります(クエリsysjobs-本当に、MS?)...

今後の読者のお役に立てれば幸いです。

3
NateJ

既存のパブリケーションへのアーティクルの追加と削除 で述べたように、パブリケーションの新しいスナップショットを作成する必要があります*。

新しい記事を追加するときにすべての記事のスナップショットを生成しないようにするには、パブリケーションプロパティimmediate_syncを0に設定する必要があります。sp_addarticle、次にsp_addsubscriptionを呼び出します。サブスクリプションがプルの場合は、sp_refreshsubscriptionsも呼び出す必要があります。次に、スナップショットを生成すると、新しく追加された記事のスナップショットのみが生成されます。

*これは、SQL Server Books Onlineで推奨されるアプローチです。アプローチの問題は、エラーが発生しやすいことです。

3

主な編集これはこの回答を完全に書き直したものです(以前のバージョンはエラーが発生しやすく、問題を引き起こす可能性があったという正当な批判を踏まえて)

これをどのように適用するかのデモも掲載しています: YouTube-SQL Serverレプリケーション:スナップショットを取得せずに記事を追加する方法

重要:これは[〜#〜]ではありません[〜#〜]Microsoftが推奨するアプローチなので、それを機能させることに関してはあなた自身で行います[〜#〜]しない[〜#〜]分離テストを大幅に行わず、手順に慣れることなく、運用環境に直接適用します。

実行する手順:

_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 procsを作成できます。

  • 手動で(間違いを犯しやすいので注意してください!)
  • 開発マシンでMSスナップショット方式を使用して記事を追加し、repl procsからスクリプトを作成します(微調整を追加する準備ができています)
  • ある種のジェネレータを作成/検索する

適用する必要がある変更:

  • sp_MSinsIF 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 Toolpack 'Generate Insert Statements ...'を使用してテーブルを抽出します。

使用する正確な方法は読者に任せますが、ディストリビューションエージェントを停止する時間にもよります。

EXTRA:テストに追加されたステップとして、ここにスクリプトを実行して(ステップ(B)から)、IUDアクションを作成するための良い場所があります[ TableNotUsingSnap]を使用して、このメソッドの信頼性を高めることができます。

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!
*/
_
2