Modification majeure
Il s'agit d'une réécriture complète de cette réponse (en tenant compte des critiques valides selon lesquelles la version précédente était sujette aux erreurs et causerait des problèmes)
Également publié une démonstration de la façon d'appliquer cela à: Youtube - Réplication SQL Server: comment ajouter un article sans prendre un instantané .
IMPORTANT: Ce n'est PAS une approche recommandée par Microsoft, donc vous serez seul pour le faire fonctionner, ne PAS appliquer directement à votre environnement de production sans tests isolés importants et vous familiariser avec les étapes!
Étapes à suivre:
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)
Vérifier:
- effectuer l'insertion sur l'éditeur - vérifier que la ligne arrive sur l'abonné
- effectuer une mise à jour sur l'éditeur - vérifier que le changement arrive sur l'abonné
- effectuer la suppression sur l'éditeur - vérifier la ligne supprimée sur l'abonné
- vérifier que les n dernières lignes sont arrivées et correspondre entre l'éditeur et l'abonné
EXEMPLE Processus
A) Créez vous-même un tableau sur votre éditeur:
/* 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) Créez vous-même un travail / proc / script pour effectuer des insertions / mises à jour / suppressions sur [TableNotUsingSnap] (vous pouvez ensuite l'utiliser pour valider la synchronisation correcte de l'abonné à l'aide de cette méthode.
Pré-étapes:
1. Créez votre table sur l'abonné
/* 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. Créez vos procédures stockées de réplication (mise à jour / insertion / suppression) - sur l'Abonné
Vous pouvez créer les proc de repl:
- Manuellement (attention car il est très facile de se tromper!)
- Ajoutez l'article à l'aide de la méthode MS Snapshot sur une machine Dev et scriptez les proc de repl (prêt pour que vous ajoutiez vos réglages)
- Créer / trouver une sorte de générateur
Le changement que vous devrez appliquer:
- sp_MSins_ [Schema] [TableName] - Ajouter
IF NOT EXISTS (SELECT 'row already exists' FROM [Schema].[TableName] dest WITH (NOLOCK) WHERE dest.Id = @c1)
pour ne pas insérer s'il est déjà là
- sp_MSupd_ [Schema] [TableName] - Commentez l'
IF @@rowcount = 0 ... exec sp_MSreplraiserror ...
ignorer une mise à jour qui n'est pas appliquée (car l'enregistrement peut avoir été supprimé sur l'éditeur avant de synchroniser les données)
- sp_MSdel_ [Schema] [TableName] - Mettez en commentaire le
IF @@rowcount = 0 ... exec sp_MSreplraiserror ...
pour ignorer une suppression qui n'est pas appliquée (car l'enregistrement peut avoir été supprimé sur l'éditeur avant de synchroniser les données)
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
ÉTAPES DE DÉPLOIEMENT
3. Arrêtez l'agent de distribution - Sur le distributeur (push) ou l'abonné (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. Ajoutez maintenant l'article à la publication - Sur l'éditeur
Paramètres clés:
sp_addarticle
- @pre_creation_cmd = N'none'
utilisé pour dire à l'agent de distribution de ne pas laisser tomber et de générer ses propres objets
sp_addsubscription
- @sync_type = N'none'
utilisé pour indiquer à Distributer qu'il n'a pas besoin de créer un nouvel instantané, il peut simplement mettre en file d'attente les commandes du DIU
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. Synchronisez vos données sur
Maintenant, vous devez copier vos données sur votre abonné, vous pouvez:
- Créer un serveur lié et le copier sur
- Utilisez l'assistant d'exportation / importation
- Restaurer une sauvegarde et appliquer des différences
- Extraire le tableau à l'aide de SSMS Toolpack 'Generate Insert Statements ...'
La méthode exacte que vous utilisez, je la laisse au lecteur, cela dépendra également de la durée pendant laquelle vous êtes prêt à faire arrêter votre agent de distribution.
EXTRA: Comme étape supplémentaire dans vos tests, voici un bon endroit pour exécuter votre script (à partir de l'étape (B)) pour créer des actions de DIU sur [TableNotUsingSnap] afin que vous puissiez gagner en confiance dans cette méthode.
6. Redémarrez l'agent de distribution - Sur le distributeur (push) ou l'abonné (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!
*/