Добавить статью в публикацию транзакций без создания нового снимка

23

При использовании транзакционной репликации SQL 2008 R2 с подписчиками по запросу, когда мы добавляем статью, я бы хотел избежать создания полного снимка (дБ составляет ~ 80 ГБ, так что это занимает часы).

Из этой статьи я видел, как сделать это с частичным снимком, отключив немедленную синхронизацию, но у нас это не сработало.

В идеале я хотел бы просто запустить это как часть нашего сценария db для создания таблицы, поэтому, если мы хотим, чтобы она реплицировалась, мы делаем:

Create Table ...    
sp_addArticle ...    
sp_PushThisToOurSubscribersNow    
user175528
источник

Ответы:

13

Вы можете добавить статью через SSMS с помощью графического интерфейса и даже применить к ней фильтры. Пока вы не измените какие-либо другие свойства статьи, вам не нужно будет создавать полный снимок.

Когда вы нажмете кнопку OK в графическом интерфейсе публикации (после добавления статьи), он будет закрыт без запроса переинициализировать - если он делает запрос на повторную инициализацию, то вы изменили то , что требует полного снимка. Если это произойдет, нажмите Отмена и попробуйте снова.

После добавления статьи вы можете просто запустить задание снимка, и вы заметите, что оно генерирует только снимок для новой статьи (так называемый мини-снимок).

Затем проверьте задание на распространение и обратите внимание, что оно создало таблицу у подписчика и массово скопировало ваши данные.

Удачи, и дайте мне знать, если вам потребуется дополнительная помощь.

NTDLS
источник
Я сделал все, что объяснялось в этом ответе, но все еще находился в ожидании синхронизации всей реплицированной базы данных. Я НЕ получил запрос на повторную инициализацию после добавления новых статей, но он все еще выполнял полную инициализацию. Быть осторожен.
JzInqXc9Dg
7
  1. Добавить новые статьи в окне свойств публикации (снимите флажок Показать только отмеченные статьи в списке)
  2. щелкните правой кнопкой мыши по тому же узлу публикации и перейдите к « Просмотр состояния агента моментальных снимков »
  3. нажмите кнопку Пуск и просто обратите внимание на журнал в тех же окнах, который показывает, что эта новая статья синхронизируется только
  4. через короткое время новые статьи будут синхронизироваться в подписчиках без инициализации всех ранее синхронизированных

введите описание изображения здесь

Иман Абиди
источник
3

У меня был тот же вопрос, и, хотя я некоторое время работал администратором базы данных, я не занимался репликацией достаточно глубоко, чтобы с ней полностью справиться, поэтому я подумал, что следующие ресурсы и руководства были полезны:

  • Этот блог , в котором представлена ​​хорошая схема процесса. Это также напоминает нам о том, что, если у вас есть большая существующая публикация, и ее опция установлена ​​на «немедленный_синхронизация», это приведет к тому, что при каждом добавлении или изменении статьи будет готовиться совершенно новый снимок. Таким образом, у него есть полезный совет, чтобы изменить эту опцию, используяsp_changePublication @publication='MyPub', @property='immediate_sync', @value='false';

  • Сообщение в блоге MSDN в "repltalk" (звучит как хороший ресурс в целом!) - не "напрямую", но все же полезно

  • Этот вопрос, где @ Brandon-Williams указал, что, если это подписка на Pull , вы также должны обновить ее, используяsp_refreshSubscriptions @publication = 'MyPub'

  • Монитор репликации SSMS - удобный способ остановки и запуска агентов (моментальных снимков, чтения журнала) при следовании руководству.

Вот фактические шаги, которые я выполнил, которые сработали хорошо и получили одобрение моего руководящего администратора баз данных:

  1. Откройте Replication Monitor, выберите публикацию, перейдите в раздел Агенты, щелкните правой кнопкой мыши Агент чтения журнала, нажмите Стоп.
  2. Установите для публикации запрет на анонимность и немедленную синхронизацию, используя sp_changePublication - да, как указывает @cody_konior, это недостаточно документировано, но в моем случае оно работало нормально. YMMV
  3. Создал таблицу у подписчика вручную с помощью скрипта, заполнил данные с помощью запроса связанного сервера (поскольку он был небольшим). Вы также можете использовать SSIS, BCP или другие средства для этого. И это может не понадобиться, если вы согласны с repl-snapshot, делающим это за вас. Я просто хотел подготовить его вручную с первого раза.
  4. Добавить статью (таблицу) используя sp_addArticle
  5. Добавьте все столбцы таблицы, используя sp_articleColumn(указанная публикация и статья, НЕ указывали столбцы -> подразумевает ВСЕ столбцы)
  6. Exec'd sp_refreshSubscriptionsдля этой публикации, чтобы обновить тягу
  7. Снова откройте Replication Monitor, выберите паб, перейдите в раздел Агенты, щелкните правой кнопкой мыши по агенту моментальных снимков и нажмите «Пуск». Он запустится один раз, создав новый снимок.
  8. Щелкните правой кнопкой мыши Log Reader Agent, нажмите «Пуск». Он будет запускаться и продолжаться в обычном режиме, и теперь ваша репликация должна снова работать.

И хотя да, вы могли бы сделать большинство изменений с помощью графического пользовательского интерфейса SSMS, я считаю полезным записать все это так, чтобы оно могло быть A) под контролем исходного кода (change-control) и B) развернуто многократно или в нескольких экземплярах , К сожалению, я не тратил время на написание сценариев остановок / запусков агента, но это не должно быть слишком сложно, учитывая, что это всего лишь задания агента SQL. Вам просто нужно проделать весь этот трюк «найти JobID с помощью Job-Name» (запрос sysjobs- действительно, MS?) ...

Надеюсь, что это поможет будущим читателям!

NateJ
источник
3

Как отмечалось в разделе «Добавление статей к удалению статей из существующих публикаций» , вы должны * создать новый снимок для публикации.

Чтобы избежать создания моментального снимка для всех статей при добавлении новой статьи, для свойства публикации immediate_syncдолжно быть установлено значение 0. Вызовите sp_addarticle, затем sp_addsubscription. Если подписки тянуть, вы также должны позвонить sp_refreshsubscriptions. Затем создайте снимок, и будет создан только снимок для только что добавленной статьи.

* Это рекомендуемый подход в электронной документации по SQL Server. Проблема вашего подхода в том, что он подвержен ошибкам.

Брэндон Уильямс
источник
2

Основное редактирование Это полное переписывание этого ответа (принимая во внимание обоснованную критику, что предыдущая версия была подвержена ошибкам и могла вызвать проблемы)

Также размещена демонстрация того, как применить это к: 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 строк прибыли и соответствуют между издателем и подписчиком

Пример процесса

А) Создайте себе таблицу на своем издателе:

/* 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) Создайте себе задание / proc / script для выполнения некоторых вставок / обновлений / удалений в [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. Создайте свои хранимые процедуры репликации (обновление / вставка / удаление) - на подписчике

Вы можете создать репл проки:

  • Вручную (будьте осторожны, так как очень легко ошибиться!)
  • Добавьте статью, используя метод MS Snapshot на компьютере разработчика, и отключите сценарии repl (готовые для добавления настроек).
  • Создать / найти какой-нибудь генератор

Изменение, которое вам нужно будет применить:

  • 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. Остановите распространителя - на распространителе (Push) или на подписчике (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. Теперь добавьте статью в публикацию - Об издателе

Основные параметры:

  • 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. Синхронизируйте ваши данные через

Теперь вам нужно скопировать ваши данные подписчику, вы можете:

  • Создайте связанный сервер и скопируйте его
  • Используйте мастер экспорта / импорта
  • Восстановите резервную копию и примените diff
  • Извлеките таблицу с помощью SSMS Toolpack «Создать операторы вставки ...»

Точный метод, который вы используете, я оставлю на усмотрение читателя, он также будет зависеть от того, как долго вы хотите, чтобы ваш агент распространителя был остановлен.

ДОПОЛНИТЕЛЬНО: В качестве дополнительного шага в ваших тестах, здесь хорошее место для запуска вашего скрипта (из шага (B)) для создания действий IUD на [TableNotUsingSnap], чтобы вы могли обрести уверенность в этом методе.

6. Перезапустите агент распространения - На распространителе (push) или на подписчике (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!
*/
Эндрю Бикертон
источник