Tambahkan artikel ke publikasi transaksional tanpa menghasilkan snapshot baru

23

Menggunakan replikasi transaksional SQL 2008 R2 dengan pelanggan tarik, ketika kita menambahkan artikel, saya ingin menghindari harus membuat seluruh snapshot (db ~ 80 GB, jadi ini membutuhkan waktu berjam-jam).

Dari artikel ini , saya telah melihat bagaimana melakukan ini dengan snapshot parsial dengan menonaktifkan direct_sync, tetapi itu tidak berhasil bagi kami.

Idealnya saya ingin menjalankan ini sebagai bagian dari skrip db kami untuk membuat tabel, jadi jika kita ingin itu direplikasi, kita lakukan:

Create Table ...    
sp_addArticle ...    
sp_PushThisToOurSubscribersNow    
pengguna175528
sumber

Jawaban:

13

Anda dapat menambahkan artikel melalui SSMS menggunakan GUI dan bahkan menerapkan filter ke dalamnya. Selama Anda tidak mengubah properti lain dari artikel ini, Anda tidak perlu membuat snapshot penuh.

Ketika Anda menekan OK di GUI publikasi (setelah menambahkan artikel), itu akan ditutup tanpa diminta untuk menginisialisasi ulang - jika memang diminta untuk menginisialisasi ulang, maka Anda telah mengubah sesuatu yang memerlukan snapshot LENGKAP. Jika itu terjadi, tekan batalkan dan coba lagi.

Setelah Anda menambahkan artikel, Anda cukup memulai pekerjaan snapshot dan Anda akan melihat bahwa itu hanya menghasilkan snapshot untuk artikel baru (disebut mini-snapshot).

Kemudian periksa pekerjaan distribusi Anda, dan perhatikan bahwa itu menciptakan tabel di pelanggan dan menyalin data Anda secara massal.

Semoga berhasil, dan beri tahu saya jika Anda memerlukan bantuan lebih lanjut.

NTDLS
sumber
Saya melakukan semuanya yang dijelaskan dalam jawaban ini tetapi masih menemukan diri saya menunggu di seluruh database yang direplikasi untuk selaras. Saya TIDAK diminta untuk menginisialisasi ulang setelah menambahkan artikel baru, tetapi masih melakukan inisialisasi penuh. Hati-hati.
JzInqXc9Dg
7
  1. Tambahkan artikel baru di jendela properti Publikasi Anda (hapus centang pada Tampilkan hanya artikel yang dicentang dalam daftar)
  2. klik kanan simpul Publikasi yang sama dan pergi ke " Lihat Status Agen Snapshot "
  3. klik mulai dan cukup catat log di jendela yang sama yang menunjukkan artikel baru ini hanya disinkronkan
  4. setelah beberapa saat artikel baru akan disinkronkan dalam pelanggan tanpa harus menginisialisasi semua yang sebelumnya disinkronkan

masukkan deskripsi gambar di sini

Iman Abidi
sumber
3

Saya memiliki pertanyaan yang sama, dan meskipun saya telah menjadi DBA untuk sementara waktu, saya belum benar-benar berurusan dengan replikasi yang cukup mendalam sehingga benar-benar nyaman dengan itu, jadi saya pikir sumber daya dan panduan berikut sangat membantu:

  • Blog ini , yang memberikan garis besar proses yang bagus. Ini juga mengingatkan kita bahwa, jika Anda memiliki publikasi besar yang sudah ada, dan opsi itu diatur ke "direct_sync", itu akan menyebabkan snapshot yang sama sekali baru disiapkan setiap kali Anda menambah atau mengubah artikel. Jadi dia punya tip praktis untuk mengubah opsi itu, menggunakansp_changePublication @publication='MyPub', @property='immediate_sync', @value='false';

  • Posting blog MSDN di "repltalk" (terdengar seperti sumber yang bagus secara umum!) - bukan "langsung secara langsung" terkait tetapi masih membantu

  • Pertanyaan ini, di mana @ Brandon-Williams menunjukkan bahwa, jika ini merupakan langganan Tarik , Anda juga harus menyegarkannya, menggunakansp_refreshSubscriptions @publication = 'MyPub'

  • Monitor Replikasi SSMS - cara mudah untuk menghentikan & memulai agen (snapshot, log-reader) saat mengikuti panduan ini.

Berikut adalah langkah-langkah aktual yang saya ikuti, yang bekerja dengan baik & mendapat persetujuan dari DBA pembimbing saya:

  1. Buka Monitor Replikasi, pilih publikasi, pergi ke Agen, klik kanan Agen Pembaca Log, klik Stop.
  2. Setel publikasi untuk tidak mengizinkan-anonim & tidak sp_changePublication-sinkronkan , menggunakan - ya, seperti yang ditunjukkan oleh @cody_konior, ini kurang terdokumentasi, tetapi itu berfungsi dengan baik dalam kasus saya. YMMV
  3. Membuat tabel di pelanggan secara manual menggunakan skrip, diisi dengan data menggunakan kueri server-tertaut (karena kecil). Anda juga bisa menggunakan SSIS, BCP, atau cara lain untuk melakukan ini. Dan itu mungkin tidak perlu, jika Anda baik-baik saja dengan snapshot-snap melakukannya untuk Anda. Saya hanya ingin menyiapkannya secara manual pertama kali.
  4. Tambahkan artikel (tabel) menggunakan sp_addArticle
  5. Tambahkan semua kolom tabel menggunakan sp_articleColumn(publikasi & artikel yang ditentukan, JANGAN tentukan kolom -> menyiratkan SEMUA kolom)
  6. Exec'd sp_refreshSubscriptionsuntuk publikasi itu untuk menyegarkan pull-er
  7. Buka Monitor Replikasi lagi, pilih pub, pergi ke Agen, klik kanan Agen Snapshot, klik "Mulai". Ini akan berjalan sekali, membuat snapshot baru.
  8. Klik kanan Agen Pembaca Log, klik "Mulai". Ini akan mulai & terus berjalan seperti biasa, & replikasi Anda sekarang akan berfungsi lagi.

Dan sementara ya, Anda bisa melakukan sebagian besar perubahan dengan GUI SSMS, saya merasa sangat membantu untuk skrip semuanya sehingga bisa A) di bawah kontrol sumber (perubahan-kontrol), dan B) digunakan berulang kali atau ke beberapa contoh . Sayangnya saya tidak menghabiskan waktu untuk menuliskan / menghentikan Agen, tapi itu tidak terlalu sulit mengingat bahwa mereka hanya SQL Agent Jobs. Anda hanya perlu melakukan keseluruhan "temukan JobID menggunakan trik Nama-Pekerjaan" (permintaan sysjobs- sungguh, MS?) ...

Harapan yang membantu pembaca masa depan!

NateJ
sumber
3

Sebagaimana tercantum dalam Menambahkan Artikel ke dan Menjatuhkan Artikel dari Publikasi yang Ada , Anda harus * membuat snapshot baru untuk publikasi.

Untuk menghindari pembuatan snapshot untuk semua artikel saat menambahkan artikel baru, properti publikasi immediate_syncharus diatur ke 0. Hubungi sp_addarticle, lalu sp_addsubscription. Jika langganan ditarik, Anda juga harus menelepon sp_refreshsubscriptions. Kemudian buat snapshot dan hanya snapshot untuk artikel yang baru ditambahkan yang akan dibuat.

* Ini adalah pendekatan yang direkomendasikan dalam SQL Server Books Online. Masalah dengan pendekatan Anda adalah bahwa ia rentan terhadap kesalahan.

Brandon Williams
sumber
2

Sunting utama Ini adalah penulisan ulang lengkap dari jawaban ini (menerima kritik yang valid bahwa versi sebelumnya rawan kesalahan dan akan menyebabkan masalah)

Juga memposting demo tentang cara menerapkan ini ke: Youtube - Replikasi SQL Server: Cara menambahkan artikel tanpa mengambil snapshot .

PENTING: Ini BUKAN pendekatan yang direkomendasikan dari Microsoft, jadi Anda akan melakukannya sendiri untuk membuatnya berfungsi, JANGAN mendaftar langsung ke lingkungan produksi Anda tanpa pengujian terisolasi yang signifikan dan buat diri Anda nyaman dengan langkah-langkahnya!

Langkah-langkah untuk diikuti:

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)

Untuk memverifikasi:

  • melakukan penyisipan pada penerbit - verifikasi baris diterima oleh pelanggan
  • melakukan pembaruan pada penerbit - verifikasi perubahan diterima oleh pelanggan
  • lakukan hapus pada penerbit - verifikasi baris yang dihapus pada pelanggan
  • verifikasi bahwa n baris terakhir telah tiba dan cocok antara penerbit dan pelanggan

CONTOH Proses

A) Buat sendiri tabel di penerbit Anda:

/* 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) Buat sendiri pekerjaan / proc / script untuk melakukan beberapa menyisipkan / memperbarui / menghapus pada [TableNotUsingSnap] (Anda kemudian dapat menggunakan ini untuk memvalidasi bagaimana pelanggan disinkronkan dengan benar menggunakan metode ini.

Pra-langkah:

1. Buat tabel Anda di pelanggan

/* 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. Buat prosedur replikasi tersimpan Anda (perbarui / masukkan / hapus) - pada Pelanggan

Anda dapat membuat procs repl:

  • Secara manual (hati-hati karena sangat mudah membuat kesalahan!)
  • Tambahkan artikel menggunakan metode MS Snapshot pada mesin Dev dan skrip dari procs repl (siap bagi Anda untuk menambahkan tweak Anda)
  • Buat / Temukan beberapa jenis generator

Perubahan yang perlu Anda terapkan:

  • sp_MSins_ [Skema] [TableName] - Tambahkan IF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1)untuk tidak memasukkan jika sudah ada
  • sp_MSupd_ [Skema] [TableName] - Berkomentar IF @@rowcount = 0 ... exec sp_MSreplraiserror ...untuk mengabaikan pembaruan yang tidak diterapkan (karena catatan mungkin telah dihapus pada penerbit sebelum Anda menyinkronkan data)
  • sp_MSdel_ [Skema] [TableName] - Mengomentari IF @@rowcount = 0 ... exec sp_MSreplraiserror ...untuk mengabaikan penghapusan yang tidak diterapkan (karena catatan mungkin telah dihapus pada penerbit sebelum Anda menyinkronkan data)

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

LANGKAH-LANGKAH PENYIMPANAN

3. Hentikan agen distribusi - Pada Distributor (Dorong) atau Pelanggan (Tarik)

/*  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. Sekarang tambahkan artikel ke publikasi - Di Penerbit

Parameter kunci:

  • sp_addarticle- @pre_creation_cmd = N'none'Digunakan untuk memberitahu agen distribusi agar tidak menjatuhkan dan membuat objek sendiri
  • sp_addsubscription- @sync_type = N'none'Digunakan untuk memberi tahu Distributor bahwa itu tidak perlu membuat snapshot baru, itu hanya dapat mengantri perintah 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. Sinkronkan data Anda di seluruh

Sekarang Anda perlu menyalin data Anda ke pelanggan Anda, Anda bisa:

  • Buat Server yang ditautkan dan salin melintasi
  • Gunakan Wisaya Ekspor / Impor
  • Kembalikan cadangan dan terapkan diff
  • Ekstrak tabel menggunakan SSMS Toolpack 'Hasilkan Pernyataan Sisipan ...'

Metode tepat yang Anda gunakan saya serahkan kepada pembaca, itu juga akan tergantung pada berapa lama Anda bersedia untuk menghentikan Agen Distribusi Anda.

EXTRA: Sebagai langkah tambahan dalam pengujian Anda, berikut adalah tempat yang bagus untuk menjalankan skrip Anda (dari Langkah (B)) untuk membuat tindakan IUD pada [TableNotUsingSnap] sehingga Anda bisa mendapatkan kepercayaan dalam metode ini.

6. Mulai ulang agen distribusi - Pada Distributor (Dorong) atau Pelanggan (Tarik)

/*  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
sumber