Dodaj artykuł do publikacji transakcyjnej bez generowania nowej migawki

23

Używając replikacji transakcyjnej SQL 2008 R2 z subskrybentami ściągającymi, kiedy dodajemy artykuł, chciałbym uniknąć konieczności tworzenia całej migawki (db wynosi ~ 80 GB, więc zajmuje to wiele godzin).

W tym artykule widziałem, jak to zrobić z częściową migawką, wyłączając natychmiastową synchronizację, ale to nie działało dla nas.

Idealnie chciałbym uruchomić to jako część naszego skryptu db, aby utworzyć tabelę, więc jeśli chcemy, aby została zreplikowana, wykonujemy:

Create Table ...    
sp_addArticle ...    
sp_PushThisToOurSubscribersNow    
użytkownik175528
źródło

Odpowiedzi:

13

Możesz dodać artykuł przez SSMS za pomocą GUI, a nawet zastosować do niego filtry. Dopóki nie zmienisz żadnych innych właściwości tego artykułu, nie będziesz musiał generować pełnej migawki.

Kiedy trafisz OK w GUI publikacji (po dodaniu artykułu), będzie zamknąć bez monitowania ponownie zainicjować - gdyby nie szybka ponownie zainicjować, a następnie zmieniłeś coś, co wymaga pełnej migawkę. Jeśli tak się stanie, naciśnij przycisk Anuluj i spróbuj ponownie.

Po dodaniu artykułu możesz po prostu uruchomić zadanie migawki, a zauważysz, że generuje ono tylko migawkę dla nowego artykułu (zwanego mini-migawką).

Następnie sprawdź swoje zadanie dystrybucji i zauważ, że utworzył on tabelę u subskrybenta i masowo skopiował twoje dane.

Powodzenia i daj mi znać, jeśli potrzebujesz dalszej pomocy.

NTDLS
źródło
Zrobiłem wszystko wyjaśnione w tej odpowiedzi, ale wciąż czekałem na synchronizację całej replikowanej bazy danych. Po dodaniu nowych artykułów NIE dostałem monitu o ponowne zainicjowanie, ale nadal wykonałem pełną inicjalizację. Bądź ostrożny.
JzInqXc9Dg
7
  1. Dodaj nowe artykuły w oknie właściwości Publikacja (odznacz opcję Pokaż tylko zaznaczone artykuły na liście)
  2. kliknij prawym przyciskiem myszy ten sam węzeł publikacji i przejdź do „ Wyświetl status agenta migawki
  3. kliknij Start i po prostu zanotuj dziennik w tych samych oknach, które pokazują, że ten nowy artykuł jest tylko zsynchronizowany
  4. po krótkim czasie nowe artykuły zostaną zsynchronizowane z subskrybentami bez inicjowania wszystkich wcześniej zsynchronizowanych

wprowadź opis zdjęcia tutaj

Iman Abidi
źródło
3

Miałem to samo pytanie i mimo że od dłuższego czasu jestem DBA, tak naprawdę nie zajmowałem się replikacją na tyle głęboko, aby czuć się z nią komfortowo, więc pomyślałem, że pomocne były następujące zasoby i przewodniki:

  • Ten blog , który przedstawił dobry zarys tego procesu. Przypomina nam również, że jeśli masz już dużą publikację, a jej opcja jest ustawiona na „natychmiastowa_synchronizacja”, spowoduje to, że za każdym razem, gdy dodasz lub zmienisz artykuł, zostanie przygotowana zupełnie nowa migawka. Ma więc praktyczną wskazówkę, aby zmienić tę opcję, używającsp_changePublication @publication='MyPub', @property='immediate_sync', @value='false';

  • Post na blogu MSDN w „repltalk” (ogólnie rzecz biorąc brzmi jak dobry zasób!) - niezwiązany „bezpośrednio”, ale nadal pomocny

  • To pytanie, w którym @ Brandon-Williams wskazał, że jeśli jest to subskrypcja Pull , należy ją również odświeżyć, używającsp_refreshSubscriptions @publication = 'MyPub'

  • Monitor replikacji SSMS - wygodny sposób na zatrzymanie i uruchomienie agentów (migawka, czytnik logów) podczas wykonywania instrukcji.

Oto rzeczywiste kroki, które wykonałem, które działały dobrze i spotkały się z aprobatą mojego nadzorującego DBA:

  1. Otwórz Monitor replikacji, wybierz publikację, przejdź do Agenty, kliknij prawym przyciskiem myszy Log Reader Agent, kliknij Stop.
  2. Ustaw publikację tak, aby nie zezwalała na anonimowość i nie na natychmiastową synchronizację, używając sp_changePublication- tak, jak wskazuje @cody_konior, jest to niedokumentowane, ale w moim przypadku działało dobrze. YMMV
  3. Tabela utworzona u subskrybenta została ręcznie utworzona za pomocą skryptu, wypełnionego danymi za pomocą zapytania połączonego z serwerem (ponieważ była mała). Możesz także skorzystać z SSIS, BCP lub innego sposobu. I może nie być konieczne, jeśli nie masz nic przeciwko migawce repl. Chciałem tylko przygotować go za pierwszym razem.
  4. Dodaj artykuł (tabelę) za pomocą sp_addArticle
  5. Dodaj wszystkie kolumny tabeli używając sp_articleColumn(określona publikacja i artykuł, NIE DOTYCZY określ kolumn -> implikuje WSZYSTKIE kolumny)
  6. Wykonane sp_refreshSubscriptionsdla tej publikacji w celu odświeżenia ściągacza
  7. Ponownie otwórz Monitor replikacji, wybierz pub, przejdź do Agentów, kliknij prawym przyciskiem myszy Agenta migawek, kliknij „Start”. Uruchomi się raz, tworząc nową migawkę.
  8. Kliknij prawym przyciskiem myszy Log Reader Agent, kliknij „Start”. Rozpocznie się i będzie działać normalnie, a Twoja replikacja powinna teraz działać ponownie.

I chociaż tak, większość zmian można wykonać za pomocą graficznego interfejsu użytkownika SSMS, uważam, że pomocne jest wykonanie skryptu w całości, aby mógł to być A) pod kontrolą źródła (kontrola zmian) i B) wdrażany wielokrotnie lub w wielu instancjach . Niestety nie spędziłem czasu na pisanie skryptów zatrzymywania / uruchamiania agenta, ale nie powinno to być zbyt trudne, biorąc pod uwagę, że są to tylko zadania agenta SQL. Musisz po prostu zrobić całą „sztuczkę JobID przy użyciu Job-Name” (zapytanie sysjobs- naprawdę, MS?) ...

Mam nadzieję, że pomoże przyszłym czytelnikom!

NateJ
źródło
3

Jak wspomniano w artykule Dodawanie artykułów i usuwanie artykułów z istniejących publikacji , należy * utworzyć nową migawkę publikacji.

Aby uniknąć generowania migawki dla wszystkich artykułów podczas dodawania nowego artykułu, właściwość publikacji immediate_syncmusi być ustawiona na 0. sp_addarticleNastępnie wywołaj sp_addsubscription. Jeśli subskrypcje są ściągane, musisz również zadzwonić sp_refreshsubscriptions. Następnie wygeneruj migawkę i wygenerowana zostanie tylko migawka dla nowo dodanego artykułu.

* Jest to zalecane podejście w SQL Server Books Online. Problem z twoim podejściem polega na tym, że jest podatny na błędy.

Brandon Williams
źródło
2

Ważna edycja Ważna Jest to kompletne przepisanie tej odpowiedzi (biorąc pod uwagę słuszną krytykę, że poprzednia wersja była podatna na błędy i powodowała problemy)

Udostępniono również demonstrację tego, jak zastosować to do: Youtube - replikacja serwera SQL: jak dodać artykuł bez robienia migawki .

WAŻNE: NIE jest to zalecane podejście Microsoftu, więc będziesz działał samodzielnie, jeśli chodzi o uruchomienie go, NIE aplikuj bezpośrednio do środowiska produkcyjnego bez znaczących izolowanych testów i poczucia komfortu podczas wykonywania kroków!

Kroki do naśladowania:

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)

Do weryfikacji:

  • wykonaj wstawianie u wydawcy - sprawdź, czy wiersz dotrze do subskrybenta
  • wykonaj aktualizację u wydawcy - sprawdź, czy subskrybent dotrze do zmiany
  • wykonaj usunięcie u wydawcy - sprawdź, czy wiersz został usunięty przez subskrybenta
  • sprawdź, czy dotarło ostatnie n wierszy i czy są zgodne między wydawcą a subskrybentem

PRZYKŁAD Proces

A) Stwórz sobie tabelę w swoim wydawcy:

/* 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) Utwórz sobie zadanie / proc / skrypt, aby wykonać wstawianie / aktualizację / usuwanie w [TableNotUsingSnap] (możesz następnie użyć tego do sprawdzenia poprawności synchronizacji subskrybenta przy użyciu tej metody.

Wstępne kroki:

1. Utwórz tabelę na subskrybencie

/* 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. Utwórz procedury składowane replikacji (aktualizuj / wstaw / usuń) - u subskrybenta

Możesz utworzyć repl procs:

  • Ręcznie (uważaj, ponieważ bardzo łatwo jest popełnić błąd!)
  • Dodaj artykuł przy użyciu metody MS Snapshot na maszynie deweloperskiej i wyłącz skrypt proc proc (gotowy do dodania poprawek)
  • Utwórz / Znajdź jakiś generator

Zmiana, którą będziesz musiał zastosować:

  • sp_MSins_ [Schema] [TableName] - Add IF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1) aby nie wstawiać, jeśli już tam jest
  • sp_MSupd_ [Schema] [TableName] - Skomentuj IF @@rowcount = 0 ... exec sp_MSreplraiserror ... aby zignorować aktualizację, która nie jest stosowana (ponieważ rekord mógł zostać usunięty przez wydawcę przed zsynchronizowaniem danych)
  • sp_MSdel_ [schemat] [nazwa_tabeli] - Skomentuj, IF @@rowcount = 0 ... exec sp_MSreplraiserror ...aby zignorować usunięcie, które nie jest stosowane (ponieważ rekord mógł zostać usunięty przez wydawcę przed zsynchronizowaniem danych)

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

KROKI WDROŻENIA

3. Zatrzymaj agenta dystrybucyjnego - na dystrybutorze (Push) lub subskrybencie (Pull)

/*  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. Teraz dodaj artykuł do publikacji - Na wydawcy

Kluczowe parametry:

  • sp_addarticle- @pre_creation_cmd = N'none'służy do informowania agenta dystrybucji, aby nie upuszczał i nie generował własnych obiektów
  • sp_addsubscription- @sync_type = N'none'używany, aby powiedzieć Distributerowi, że nie musi tworzyć nowej migawki, może po prostu ustawiać w kolejce polecenia 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. Zsynchronizuj swoje dane

Teraz musisz skopiować swoje dane do subskrybenta, możesz:

  • Utwórz połączony serwer i skopiuj go
  • Użyj Kreatora eksportu / importu
  • Przywróć kopię zapasową i zastosuj różnice
  • Wyodrębnij tabelę za pomocą pakietu narzędzi SSMS „Generuj instrukcje wstawiania ...”

Dokładną metodę, której używasz, pozostawiam czytelnikowi, będzie to również zależeć od tego, jak długo jesteś gotów zatrzymać Agenta Dystrybucyjnego.

DODATKOWO: Jako dodatkowy krok w twoich testach, tutaj jest dobre miejsce do uruchomienia skryptu (od kroku (B)), aby utworzyć akcje IUD na [TableNotUsingSnap], abyś mógł zyskać zaufanie do tej metody.

6. Uruchom ponownie agenta dystrybucji - na dystrybutorze (Push) lub subskrybencie (Pull)

/*  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!
*/
Andrew Bickerton
źródło