it-swarm.it

Aggiungi l'articolo alla pubblicazione transazionale senza generare una nuova istantanea

Utilizzando la replica transazionale di SQL 2008 R2 con abbonati pull, quando aggiungiamo un articolo, vorrei evitare di dover creare un'intera istantanea (il db è ~ 80 GB, quindi ci vogliono ore).

Da questo articolo , ho visto come farlo con uno snapshot parziale disattivando immediate_sincronizzazione, ma per noi non ha funzionato.

Idealmente, vorrei solo eseguire questo come parte del nostro script db per creare la tabella, quindi se lo vogliamo replicato facciamo:

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

È possibile aggiungere l'articolo tramite SSMS utilizzando la GUI e persino applicare filtri ad esso. Finché non si modifica alcuna delle altre proprietà dell'articolo non sarà necessario generare uno snapshot completo.

Quando premi OK nella GUI della pubblicazione (dopo aver aggiunto l'articolo), si chiuderà senza richiedere la reinizializzazione - se lo fa Richiedi di reinizializzare, allora hai cambiato qualcosa che richiede uno snapshot COMPLETO. In tal caso, premi annulla e riprova.

Dopo aver aggiunto l'articolo, puoi semplicemente avviare il processo di istantanea e noterai che genera solo un'istantanea per il nuovo articolo (chiamato mini-istantanea).

Quindi controlla il tuo processo di distribuzione e nota che ha creato la tabella nell'abbonato e copiato in massa i tuoi dati.

Buona fortuna e fammi sapere se hai bisogno di ulteriore assistenza.

13
NTDLS
  1. Aggiungi nuovi articoli nella finestra della proprietà Pubblicazione (deseleziona Mostra solo gli articoli selezionati nell'elenco)
  2. fai clic con il pulsante destro del mouse sullo stesso nodo Pubblicazione e vai a " Visualizza lo stato dell'agente snapshot "
  3. fai clic su start e osserva il registro nella stessa finestra che mostra che questo nuovo articolo è solo sincronizzato
  4. dopo poco tempo i nuovi articoli verranno sincronizzati negli abbonati senza andare a inizializzare tutti quelli precedentemente sincronizzati

enter image description here

8
Iman Abidi

Avevo la stessa domanda, e anche se sono stato un DBA per un po ', non ho davvero affrontato la replica abbastanza profondamente da sentirmi completamente a mio agio, quindi ho pensato che le seguenti risorse e guide fossero utili:

  • Questo blog , che ha fornito una buona descrizione del processo. Ci ricorda inoltre che, se si dispone di una pubblicazione esistente di grandi dimensioni, e l'opzione è impostata su "immediate_sincronizzazione", verrà preparata un'istantanea completamente nuova ogni volta che si aggiunge o si modifica un articolo. Quindi ha un suggerimento utile per cambiare questa opzione, usando sp_changePublication @publication='MyPub', @property='immediate_sync', @value='false';

  • post sul blog MSDN in "repltalk" (suona come una buona risorsa in generale!) - non "direttamente diretto" ma comunque utile

  • Questa domanda, in cui @ Brandon-Williams ha sottolineato che, se si tratta di un abbonamento Pull , dovresti anche aggiornarlo, usando sp_refreshSubscriptions @publication = 'MyPub'

  • Monitoraggio replica SSMS - modo conveniente per arrestare e avviare gli agenti (snapshot, log-reader) quando si segue la guida.

Ecco i passaggi che ho seguito, che ha funzionato bene e ha incontrato l'approvazione del mio DBA supervisore:

  1. Apri Replication Monitor, seleziona la pubblicazione, vai su Agenti, fai clic con il pulsante destro del mouse su Log Reader Agent, fai clic su Stop.
  2. Imposta la pubblicazione in modo che non consenta la sincronizzazione anonima e non immediata, usando sp_changePublication - sì, come sottolinea @cody_konior, questo è sotto documentato, ma ha funzionato bene nel mio caso. YMMV
  3. Creata manualmente la tabella nell'abbonato utilizzando lo script, piena di dati utilizzando la query del server collegato (poiché era piccola). Puoi anche utilizzare SSIS, BCP o altri mezzi per farlo. E potrebbe non essere necessario, se stai bene con l'istantanea di sostituzione che lo fa per te. Volevo solo prepararlo manualmente la prima volta.
  4. Aggiungi l'articolo (tabella) usando sp_addArticle
  5. Aggiungi tutte le colonne della tabella usando sp_articleColumn (pubblicazione e articolo specificati, DIDN'T specifica colonne -> implica TUTTE le colonne)
  6. Exec'd sp_refreshSubscriptions per quella pubblicazione per aggiornare il pull-er
  7. Apri nuovamente Replication Monitor, seleziona il pub, vai su Agenti, fai clic con il pulsante destro del mouse su Snapshot Agent, fai clic su "Avvia". Verrà eseguito una volta, creando la nuova istantanea.
  8. Fare clic con il tasto destro del mouse su Log Reader Agent, fare clic su "Start". Si avvierà e continuerà a funzionare normalmente e la replica dovrebbe ora funzionare di nuovo.

E mentre sì, tu could fai la maggior parte delle modifiche con la GUI di SSMS, trovo utile scrivere tutto in modo che possa essere A) sotto il controllo del codice sorgente (controllo delle modifiche), e B) distribuito ripetutamente o in più istanze. Sfortunatamente non ho trascorso il tempo a scrivere script sugli arresti/avviamenti dell'agente, ma non dovrebbe essere troppo difficile dato che sono solo lavori dell'agente SQL. Devi solo fare tutto il trucco "trova il JobID usando il Job-Name" trucco (query sysjobs - davvero, MS?) ...

Spero che aiuti i futuri lettori!

3
NateJ

Come indicato in Aggiunta di articoli e eliminazione di articoli da pubblicazioni esistenti , è necessario * creare una nuova istantanea per la pubblicazione.

Per evitare di generare un'istantanea per tutti gli articoli quando si aggiunge un nuovo articolo, proprietà di pubblicazione immediate_sync deve essere impostato su 0. Chiama sp_addarticle, poi sp_addsubscription. Se gli abbonamenti vengono estratti, devi anche chiamare sp_refreshsubscriptions. Quindi genera un'istantanea e verrà generata solo un'istantanea per l'articolo appena aggiunto.

* Questo è l'approccio consigliato nella documentazione online di SQL Server. Il problema con il tuo approccio è che è soggetto a errori.

3
Brandon Williams

Modifica principale Questa è una riscrittura completa di questa risposta (prendendo in considerazione le valide critiche secondo cui la versione precedente era soggetta a errori e avrebbe causato problemi)

Ha anche pubblicato una demo di come applicare questo a: Youtube - Replica di SQL Server: come aggiungere un articolo senza fare uno snapshot .

IMPORTANTE: Questo è [~ # ~] non [~ # ~] un approccio raccomandato da Microsoft, quindi sarai da solo per quanto riguarda il funzionamento, fai [~ # ~] non [~ # ~] applica direttamente al tuo ambiente di produzione senza significativi test isolati e mettiti comodo con i passaggi!

Passaggi da seguire:

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)

Verificare:

  • esegue l'inserimento sull'editore: verifica che la riga arrivi sull'abbonato
  • esegui l'aggiornamento sull'editore: verifica che la modifica arrivi sull'abbonato
  • esegue l'eliminazione sull'editore: verifica la riga eliminata sull'abbonato
  • verifica che le ultime n righe siano arrivate e corrispondano tra editore e abbonato

Processo ESEMPIO

A) Crea una tabella sul tuo editore:

/* 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) Crea un lavoro/proc/script per eseguire alcuni inserimenti/aggiornamenti/eliminazioni su [TableNotUsingSnap] (puoi quindi utilizzarlo per convalidare correttamente la sincronizzazione dell'abbonato usando questo metodo.

Pre-fasi:

1. Crea la tua tabella sull'abbonato

/* 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. Creare le stored procedure di replica (aggiorna/inserisci/elimina) - sul Sottoscrittore

È possibile creare i proc di sostituzione:

  • Manualmente (fai attenzione perché è molto facile fare un errore!)
  • Aggiungi l'articolo usando il metodo MS Snapshot su una macchina Dev e esegui lo script fuori dai proc di sostituzione (pronto per aggiungere le tue modifiche)
  • Crea/Trova un qualche tipo di generatore

La modifica che dovrai applicare:

  • sp_MSinsIF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1) da non inserire se è già presente
  • sp_MSupd_ [Schema] [TableName] - Commenta IF @@rowcount = 0 ... exec sp_MSreplraiserror ... per ignorare un aggiornamento che non viene applicato (poiché il record potrebbe essere stato cancellato sull'editore prima di sincronizzare i dati)
  • sp_MSdel_ [Schema] [TableName] - Commenta IF @@rowcount = 0 ... exec sp_MSreplraiserror ... per ignorare un'eliminazione che non viene applicata (poiché il record potrebbe essere stato eliminato sull'editore prima di sincronizzare i dati)

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]', @[email protected]_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]', @[email protected]_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]', @[email protected]_text, @param3=13234
        End */
end
GO

PASSAGGI DI DEPLOYMENT

3. Arresta l'agente di distribuzione - Sul distributore (Push) o sul Sottoscrittore (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. Ora aggiungi l'articolo alla pubblicazione - On the Publisher

Parametri chiave:

  • sp_addarticle - @pre_creation_cmd = N'none' Utilizzato per indicare all'agente di distribuzione di non rilasciare e generare i propri oggetti
  • sp_addsubscription - @sync_type = N'none' Usato per dire al Distributore che non ha bisogno di creare una nuova istantanea, può semplicemente mettere in coda i comandi 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. Sincronizza i tuoi dati su

Ora devi copiare i tuoi dati sul tuo abbonato, potresti:

  • Creare un server collegato e copiarlo
  • Utilizzare la procedura guidata di esportazione/importazione
  • Ripristina un backup e applica le differenze
  • Estrai la tabella usando SSMS Toolpack "Genera istruzioni di inserimento ..."

Il metodo esatto che usi lascio al lettore, dipenderà anche da quanto tempo sarai disposto a far fermare il tuo agente di distribuzione.

EXTRA: Come passaggio aggiuntivo nei test, ecco un buon punto per eseguire lo script (dal passaggio (B)) per creare azioni IUD su [ TableNotUsingSnap] in modo da poter acquisire sicurezza in questo metodo.

6. Riavvia l'agente di distribuzione - Sul distributore (Push) o sul Sottoscrittore (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!
*/
2
Andrew Bickerton