Hauptbearbeitung
Dies ist eine vollständige Neufassung dieser Antwort (unter Berücksichtigung der berechtigten Kritik, dass die vorherige Version fehleranfällig war und Probleme verursachen würde).
Veröffentlichte auch eine Demo, wie man dies anwendet auf: Youtube - SQL Server Replication: Wie man einen Artikel hinzufügt, ohne einen Schnappschuss zu machen .
WICHTIG: Dies ist KEIN empfohlener Ansatz von Microsoft. Sie sind also auf sich allein gestellt, wenn es darum geht, das Produkt zum Laufen zu bringen. Sie sollten sich NICHT direkt an Ihre Produktionsumgebung wenden, ohne umfangreiche Einzeltests durchzuführen und sich mit den Schritten vertraut zu machen.
Schritte zum folgen:
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)
Verifizieren:
- Einfügung beim Publisher durchführen - Überprüfen, ob die Zeile beim Abonnenten eintrifft
- Update für Publisher durchführen - Vergewissern Sie sich, dass die Änderung beim Abonnenten eintrifft
- Löschvorgang für Publisher ausführen - Überprüfen Sie, ob die Zeile für den Abonnenten gelöscht wurde
- Vergewissern Sie sich, dass die letzten n Zeilen eingetroffen sind, und stimmen Sie zwischen Herausgeber und Abonnent überein
BEISPIEL Verfahren
A) Erstellen Sie sich eine Tabelle auf Ihrem Verlag:
/* 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) Erstellen Sie sich einen Job / einen Prozess / ein Skript, um einige Einfügungen / Aktualisierungen / Löschungen in [TableNotUsingSnap] vorzunehmen (Sie können dies dann verwenden, um zu überprüfen, wie der Abonnent mit dieser Methode korrekt synchronisiert wird.
Vorschritte:
1. Erstellen Sie Ihre Tabelle auf dem Abonnenten
/* 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. Erstellen Sie Ihre gespeicherten Replikationsprozeduren (Aktualisieren / Einfügen / Löschen) - auf dem Abonnenten
Sie können die Repl-Procs erstellen:
- Manuell (Vorsicht, es ist sehr leicht, einen Fehler zu machen!)
- Fügen Sie den Artikel mithilfe der MS Snapshot-Methode auf einem Dev-Computer hinzu und erstellen Sie ein Skript für die Repl-Procs (fertig, damit Sie Ihre Tweaks hinzufügen können).
- Erstellen / Finden Sie eine Art Generator
Die Änderung, die Sie anwenden müssen:
- sp_MSins_ [Schema] [TableName] - Hinzufügen,
IF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1)
um nicht einzufügen, wenn es bereits vorhanden ist
- sp_MSupd_ [Schema] [TableName] - Kommentieren Sie das aus
IF @@rowcount = 0 ... exec sp_MSreplraiserror ...
, um ein Update zu ignorieren, das nicht angewendet wird (da der Datensatz möglicherweise auf dem Publisher gelöscht wurde, bevor Sie die Daten synchronisiert haben).
- sp_MSdel_ [Schema] [TableName] - Kommentieren Sie das aus
IF @@rowcount = 0 ... exec sp_MSreplraiserror ...
, um ein Löschen zu ignorieren, das nicht angewendet wird (da der Datensatz möglicherweise auf dem Publisher gelöscht wurde, bevor Sie die Daten synchronisiert haben).
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
ENTWICKLUNGSSCHRITTE
3. Stoppen Sie den Verteilungsagenten - Auf dem Verteiler (Push) oder Abonnenten (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. Fügen Sie nun den Artikel zur Publikation hinzu - Auf dem Verlag
Schlüsselparameter:
sp_addarticle
- @pre_creation_cmd = N'none'
Wird verwendet, um den Distributionsagenten anzuweisen, keine eigenen Objekte abzulegen und zu generieren
sp_addsubscription
- @sync_type = N'none'
Wird verwendet, um Distributer mitzuteilen, dass kein neuer Snapshot erstellt werden muss, sondern nur die IUD-Befehle in die Warteschlange gestellt werden können
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. Synchronisieren Sie Ihre Daten über
Jetzt müssen Sie Ihre Daten auf Ihren Abonnenten kopieren. Sie können:
- Erstellen Sie einen Verbindungsserver und kopieren Sie ihn über
- Verwenden Sie den Export / Import-Assistenten
- Stellen Sie ein Backup wieder her und wenden Sie Diffs an
- Extrahieren Sie die Tabelle mit dem SSMS-Toolpack 'Insert-Anweisungen generieren ...'.
Die genaue Methode, die Sie verwenden, überlasse ich dem Leser. Sie hängt auch davon ab, wie lange Sie bereit sind, Ihren Distributionsagenten anzuhalten.
EXTRA: Als zusätzlichen Schritt in Ihren Tests ist hier ein guter Punkt, um Ihr Skript (ab Schritt (B)) auszuführen und IUP-Aktionen für [TableNotUsingSnap] zu erstellen, damit Sie Vertrauen in diese Methode gewinnen können.
6. Starten Sie den Verteilungsagenten neu - Auf dem Verteiler (Push) oder Abonnenten (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!
*/