há uma configuração de publicador --> distribuidor --> assinante e tudo foi bem configurado neste sistema e alguns testes simples de adição de algumas tabelas e reposicionamento de tabelas parecem funcionar bem.
O problema é que temos mais de 6 mil artigos por banco de dados e muitos bancos de dados em um sistema multilocatário. O sistema está em operação há mais de 20 anos e quase todos os bancos de dados pegaram pilhas e visualizações ou procedimentos armazenados não compiláveis. Não podemos apontar e clicar cada vez que um banco de dados é restaurado e/ou precisa ser republicado/publicado; portanto, o seguinte está sendo testado.
Entendo que isso pode ser programado, mas estamos seguindo este conselho para reposicionar tabelas .
O teste inicial
- Crie a assinatura com 1 artigo tblAccountingBatch.
- Execute o script abaixo para adicionar todas as tabelas com uma PK e todos os artigos compiláveis.
- Execute novamente o agente de snapshot e pegue as novas tabelas.
Os resultados
- A interface do usuário mostra que todos os ~5 mil artigos estão ativos e selecionados na sub.
- O snapshot é executado e gera 1 artigo para a tabela inicial, tblAccountingBatch.
- EXEC sp_helpsubscription mostra apenas uma tabela - tblAccountingBatch.
- Tento criar um script para adicionar outro que esteja marcado na interface do usuário usando sp_addarticle e recebo um erro informando que o artigo já foi adicionado.
Alguém sabe onde a desconexão pode estar. O snapshot não parece ver os artigos adicionados após a criação do sub.
Me deparei com este KB que descreve algo muito semelhante; no entanto, o DBA diz que esses patches foram aplicados nos ambientes de teste.
Script para adicionar todos os artigos válidos após a criação da assinatura
SET NOCOUNT ON
USE VP_UPS_V05
GO
DECLARE @PublicationName NVARCHAR(200) = 'UPS_PUB'
EXEC sp_changepublication @publication = @PublicationName, @property = 'allow_anonymous' , @value = 'false'
EXEC sp_changepublication @publication = @PublicationName, @property = 'immediate_sync' , @value = 'false'
IF(CHARINDEX('VP_',DB_NAME()) = 0 OR CHARINDEX('_V05',DB_NAME()) =0 ) BEGIN
RAISERROR('This script can only be applied against a Client database', 16, 1)
RETURN
END
DECLARE @Debug BIT = 0
DECLARE @FullName nvarchar(1000);
DECLARE @ShortName nvarchar(300)
DECLARE @ObjectType nvarchar(300)
DECLARE @HasPrimaryKey BIT
DECLARE @Sql nvarchar(1000);
DECLARE @Result int;
DECLARE @Exceptions TABLE(ShortName NVARCHAR(300), FullName NVARCHAR(300),ObjectType NVARCHAR(300), Result INT, ErrorMessage NVARCHAR(MAX))
DECLARE @IgnoredTables TABLE (TableName NVARCHAR(100))
INSERT INTO @IgnoredTables VALUES
('tblAccountingBatch')
DECLARE ObjectCursor CURSOR FOR
SELECT
ShortName,LongName,ObjectType,HasPrimaryKey
FROM
(
SELECT
OBJECT_NAME(o.object_id) ShortName ,
QUOTENAME(SCHEMA_NAME(o.schema_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)) LongName,
CASE WHEN type_desc = 'USER_TABLE' THEN CASE WHEN OBJECTPROPERTY(o.object_id,'tablehasprimaryKey') = 1 THEN 1 ELSE 0 END ELSE 0 END AS HasPrimaryKey,
type_desc AS ObjectType,
CASE
WHEN type_desc='USER_TABLE' THEN 0
WHEN type_desc='VIEW' THEN 1
WHEN type_desc='SQL_SCALAR_FUNCTION' THEN 2
WHEN type_desc='SQL_TABLE_VALUED_FUNCTION' THEN 3
WHEN type_desc='SQL_INLINE_TABLE_VALUED_FUNCTION' THEN 4
WHEN type_desc='SQL_TRIGGER' THEN 5
WHEN type_desc='SQL_STORED_PROCEDURE' THEN 6
ELSE
7
END AS ProcessOrder
FROM
sys.objects o
LEFT OUTER JOIN @IgnoredTables IgnoredTable ON type_desc = 'USER_TABLE' AND IgnoredTable.TableName = OBJECT_NAME(o.object_id)
WHERE
type_desc IN ('USER_TABLE','SQL_STORED_PROCEDURE','SQL_TRIGGER','SQL_SCALAR_FUNCTION','SQL_TABLE_VALUED_FUNCTION','SQL_INLINE_TABLE_VALUED_FUNCTION','VIEW')
AND
ISNULL(OBJECTPROPERTY(o.object_id, 'IsSchemaBound'), 0) = 0
AND
SCHEMA_NAME(o.schema_id)='dbo'
AND
IgnoredTable.TableName IS NULL
AND
((type_desc = 'USER_TABLE' AND OBJECT_NAME(o.object_id) LIKE 'tbl%')OR(type_desc<>'USER_TABLE'))
)AS X
Order BY ProcessOrder, ShortName;
--RETURN
OPEN ObjectCursor;
DECLARE @TotalObjects INT = @@CURSOR_ROWS
DECLARE @CurrentObject INT = 0
FETCH NEXT FROM ObjectCursor INTO @ShortName, @FullName, @ObjectType, @HasPrimaryKey
DECLARE @IsError BIT = 0
DECLARE @CompileResult BIT = 0
DECLARE @ErrorMessage NVARCHAR(MAX)
DECLARE @InsertCommand NVARCHAR(300)
DECLARE @DeleteCommand NVARCHAR(300)
DECLARE @UpdateCommand NVARCHAR(300)
DECLARE @ArticleType NVARCHAR(300)
WHILE @@FETCH_STATUS = 0
BEGIN
SET @CurrentObject = @CurrentObject + 1
PRINT 'Processing Object '+CAST(@CurrentObject AS VARCHAR(10))+'/'+CAST(@TotalObjects AS VARCHAR(10))+' - '+@ObjectType+' '+@ShortName
SET @IsError = 0
SET @ErrorMessage = ''
IF(@ObjectType = 'USER_TABLE') BEGIN
IF(@HasPrimaryKey = 0 ) BEGIN
SET @IsError = 1
SET @ErrorMessage = 'Missing Primary Key'
END
END ELSE BEGIN
SET @Sql = N'EXEC sp_refreshsqlmodule ''' + @FullName + '''';
BEGIN TRY
EXEC @CompileResult = sp_executesql @Sql;
IF @CompileResult <> 0 RAISERROR('Failed', 16, 1);
END TRY
BEGIN CATCH
SET @IsError = 1
SET @ErrorMessage = ERROR_MESSAGE()
END CATCH
END
IF(@IsError = 0 AND @Debug=0) BEGIN
BEGIN TRY
IF(@ObjectType = 'USER_TABLE') BEGIN
SET @InsertCommand = 'CALL sp_MSins_dbo_'+@ShortName
SET @DeleteCommand = 'CALL sp_MSdel_dbo_'+@ShortName
SET @UpdateCommand = 'CALL sp_MSupd_dbo_'+@ShortName
exec sp_addarticle
@publication = @PublicationName,
@article = @ShortName,
@source_owner = 'dbo',
@source_object = @ShortName,
@type = 'logbased',
@description = null,
@creation_script = null,
@pre_creation_cmd = 'drop',
@schema_option = 0x000000000803509F,
@identityrangemanagementoption = 'manual',
@destination_table = @ShortName,
@destination_owner = 'dbo',
@vertical_partition = 'false',
@ins_cmd = @InsertCommand,
@del_cmd = @DeleteCommand,
@upd_cmd = @UpdateCommand
END ELSE IF (@ObjectType IN ('SQL_INLINE_TABLE_VALUED_FUNCTION','SQL_SCALAR_FUNCTION','SQL_STORED_PROCEDURE','SQL_TABLE_VALUED_FUNCTION','VIEW')) BEGIN
IF(@ObjectType='SQL_STORED_PROCEDURE')
SET @ArticleType = 'proc schema only'
ELSE IF(@ObjectType = 'VIEW')
SET @ArticleType = 'view schema only'
ELSE
SET @ArticleType ='func schema only'
exec sp_addarticle
@publication =@PublicationName,
@article = @ShortName,
@source_owner = 'dbo',
@source_object = @ShortName,
@type = @ArticleType,
@description = null,
@creation_script = null,
@pre_creation_cmd = N'drop',
@schema_option = 0x0000000008000001,
@destination_table = @ShortName,
@destination_owner = 'dbo'
END
END TRY
BEGIN CATCH
SET @IsError = 1
SET @ErrorMessage = 'Could Not Add Article to Replication - '+ERROR_MESSAGE()
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
END CATCH
END
IF(@IsError = 1)
INSERT INTO @Exceptions SELECT @ShortName, @FullName, @ObjectType, 0, @ErrorMessage
FETCH NEXT FROM ObjectCursor INTO @ShortName, @FullName, @ObjectType, @HasPrimaryKey
END
CLOSE ObjectCursor;
DEALLOCATE ObjectCursor;
SELECT * FROM @Exceptions
Respondendo a isso eu mesmo. Eu encontrei muitas variações relacionadas a isso. No meu caso, tudo se resume ao fato de que eu não estava executando um rastreamento ao adicionar artigos na IU. Eu encontrei uma postagem que afirma que uma chamada para
sp_refreshsubscriptions
é garantida às vezes. Foi isso que eu perdi.Pelas observações, e por favor me corrija se eu estiver errado, o primeiro instantâneo só precisa:
Depois disso, os artigos adicionados usando allow_anonymous e immediate_sync só precisam de: