Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A partir do SQL Server 2019 (15.x) CU13, você pode configurar a replicação ponto a ponto para resolver conflitos automaticamente, permitindo que a inserção ou atualização mais recente ganhe o conflito. Se uma das gravações excluir a linha, o SQL Server permitirá que a exclusão ganhe o conflito. Esse método é conhecido como última gravação ganha.
Use procedimentos armazenados para configurar as vitórias de última gravação. Não use o Assistente de Topologia Ponto a Ponto para adicionar ou remover nós ao usar o último gravador.
Considerações de configuração importantes
Observação
Depois de atualizar para o SQL Server 2019 (15.x) CU13 ou uma versão posterior, quando você configura uma publicação com resolução de conflitos definida para a última gravação ganha, metadados extras são incluídos na publicação. Se você desinstalar/fazer downgrade posteriormente para uma versão anterior ao SQL Server 2019 (15.x) CU13, esses metadados extras causarão problemas. Você deve descartar essas publicações antes de fazer downgrade e recriá-las na versão inferior.
Ao configurar a replicação ponto a ponto com a descoberta e a resolução automáticas de conflitos para resolver conforme a última gravação vence, inclua as seguintes configurações e configurações:
Crie a publicação com os seguintes parâmetros,
Defina
@p2p_conflictdetection_policy = 'lastwriter'para especificar as últimas vitórias de gravação. Consulte sp_addpublication (Transact-SQL). Esse parâmetro é introduzido no SQL Server 2019 (15.x) CU13. O valororiginatoridpadrão resolve conflitos com base na ID do originador e é o mesmo que a resolução de conflitos antes do SQL Server 2019 (15.x) CU13.Defina
@p2p_continue_onconflict = 'true'para permitir que o agente de distribuição resolva o conflito.
Ao adicionar o artigo (
sp_addarticle), confirme o comportamento do tipo de comando para o comando de atualização (@upd_cmd). As opções incluem:-
CALL(Padrão) SCALL
Veja os detalhes em sp_addarticle.
-
Quando você adiciona um artigo (
sp_addarticle) em uma publicação com uma política de detecção de conflitos do último gravador, usarCALLouSCALLcomo tipo de comando para@upd_cmdparâmetro éCALLpadrão.Observação
O SQL Server é
SCALLcompatível com@upd_cmd. ComSCALL, quando uma transação atualiza um valor para o mesmo valor, ela não é considerada como uma alteração eSCALLo formato não fornece o valor para colunas que não são atualizadas ou modificadas. Para obter mais informações sobre o formato de chamada SCALL, consulte Sintaxe de chamada para procedimentos armazenados.Você pode usar a publicação ponto a ponto com a detecção e a resolução de conflitos do último gravador em um grupo de disponibilidade. Consulte:
Você pode ver o conflito e sua resolução.
- No SQL Server Management Studio, clique com o botão direito do mouse na publicação e selecione Exibir Conflitos.
Ou
-
conflict_schemaname_tablenameConsulta no banco de dados de publicação. Por exemplo,conflict_dbo_tab1. Consulte conflict_<schema>_<table> (Transact-SQL).
Os conflitos de inserção e atualização são resolvidos com base no último gravador, mas a exclusão sempre prevalece. Por exemplo, se você tiver conflito de exclusão-atualização e a atualização tiver sido feita posteriormente, a exclusão ainda vencerá.
A detecção e a resolução de conflitos do último gravador são determinadas com base em uma coluna
$sys_mw_cd_idoculta. O tipo de dados dessa coluna é datetime2.
Comparação de detecção de conflitos
A tabela a seguir compara como os conflitos são detectados e resolvidos com a replicação ponto a ponto tradicional e quando a resolução de conflitos do último gravador está habilitada:
| Tipo de conflito | Detalhes do conflito | Ponto a ponto | Último gravador |
|---|---|---|---|
| Insert-Insert | Todas as linhas em cada tabela que participam da replicação ponto a ponto são identificadas exclusivamente usando valores de chave primária. Um conflito de inserção ocorre quando uma linha com o mesmo valor de chave foi inserida em mais de um nó. | Se a linha de entrada for a vencedora, atualizaremos a linha de destino. Em ambos os casos, registramos as informações. | Se a linha de entrada for a vencedora, atualizaremos a linha de destino. Em ambos os casos, registramos as informações. |
| Update-Update | Ocorre quando a mesma linha foi atualizada em mais de um nó. | Se a linha de entrada for a vencedora, modificaremos SOMENTE as colunas alteradas. | Se a linha de entrada for o vencedor, modificaremos todas as colunas no destino (se @upd_cmd for definido como default – CALL). |
| Update-Insert | Ocorre se uma linha foi atualizada em um nó, mas a mesma linha foi excluída e reinserida em outro nó. | Se a linha de entrada for a vencedora, modificaremos SOMENTE as colunas alteradas. | Isso ocorre quando uma linha é atualizada peer1 e a mesma linha é excluída e reinserida.peer2 Quando a sincronização ocorre, a linha ativada peer1 é excluída, pois a exclusão sempre vence e, em seguida, a mesma linha é inserida, enquanto a linha é atualizada peer2 como atualizada ocorreu posteriormente. Isso leva à não conexão. |
| Inserir - Atualizar | Ocorre se uma linha foi excluída e reinserida em um nó e a mesma linha foi atualizada em outro nó. | Se a linha de entrada for a vencedora, atualizaremos todas as colunas. | Isso ocorre quando uma linha é excluída e reinserida peer1 e a mesma linha é atualizada peer2. Quando a sincronização ocorre, a linha é excluída peer2 , pois a exclusão sempre vence e, em seguida, é inserida novamente. Ativado peer1, a atualização é ignorada. |
| Delete-Insert Insert-Delete |
Ocorre se uma linha foi excluída em um nó, mas a mesma linha foi excluída e reinserida em outro nó. | No momento, achamos isso como conflito de D-U e, se a linha de entrada for vencedora, excluiremos a linha do destino. | Isso ocorre quando uma linha é excluída peer1 e a mesma linha é excluída + reinserida.peer2 Quando a sincronização ocorre, a linha ativada peer2 é excluída, enquanto a linha é inserida em peer1. Isso ocorre porque não armazenamos informações sobre a linha excluída, portanto, não sabemos se a linha foi excluída ou não estava presente no par. Isso leva à não conexão. |
| Delete-Update | Ocorre se uma linha foi excluída em um nó, mas a mesma linha foi atualizada em outro nó. | No momento, achamos isso como conflito de D-U e, se a linha de entrada for o vencedor, excluiremos a linha do destino. | Este é um conflito D-U. Como a exclusão sempre vence, a exclusão de entrada é o vencedor e excluimos a linha do destino. |
| Update-Delete | Ocorre se uma linha foi atualizada em um nó, mas a mesma linha foi excluída em outro nó. | No procedimento armazenado atualização ponto a ponto, se houver um conflito U-D, imprimiremos a mensagem a seguir e não a resolveremos.An update-delete conflict was detected and unresolved. The row could not be updated since the row does not exist. |
Este é um conflito U-D. Como a exclusão sempre vence, a atualização de entrada é ignorada. |
| Delete-Delete | Ocorre quando uma linha foi excluída em mais de um nó. | No procedimento armazenado Excluir ponto a ponto, se houver conflito D-D, não processaremos nenhuma alteração, basta registrá-lo. | Se houver conflito D-D, então não processaremos nenhuma alteração, basta registrá-la. |
Observação
Na implementação atual da política de detecção de conflitos do último gravador, a exclusão sempre vence quando há um conflito de inserção, exclusão-inserção ou exclusão de atualização.
Exemplos
Criar publicação no primeiro par (Node1)
Neste exemplo, o script:
- Publica um banco de dados chamado
MWPubDB. - Nomeia a publicação
PublMW. - Configura a política de detecção e resolução de conflitos conforme a última gravação vence:
, @p2p_continue_onconflict= 'true', @p2p_conflictdetection_policy = 'lastwriter'
USE [MWPubDB];
EXECUTE sp_replicationdboption
@dbname = N'MWPubDB',
@optname = N'publish',
@value = N'true';
GO
-- Adding the transactional publication
USE [MWPubDB];
EXECUTE sp_addpublication
@publication = N'PublMW',
@description = N'Peer-to-Peer publication of database ''MWPubDB'' from Publisher ''Node1''.',
@sync_method = N'native',
@retention = 0,
@allow_push = N'true',
@allow_pull = N'true',
@allow_anonymous = N'false',
@enabled_for_internet = N'false',
@snapshot_in_defaultfolder = N'true',
@compress_snapshot = N'false',
@ftp_port = 21,
@allow_subscription_copy = N'false',
@add_to_active_directory = N'false',
@repl_freq = N'continuous',
@status = N'active',
@independent_agent = N'true',
@immediate_sync = N'true',
@allow_sync_tran = N'false',
@allow_queued_tran = N'false',
@allow_dts = N'false',
@replicate_ddl = 1,
@allow_initialize_from_backup = N'true',
@enabled_for_p2p = N'true',
@enabled_for_het_sub = N'false',
@p2p_conflictdetection = N'true',
@p2p_originator_id = 100,
@p2p_continue_onconflict = 'true',
@p2p_conflictdetection_policy = 'lastwriter';
GO
USE [MWPubDB];
EXECUTE sp_addarticle
@publication = N'PublMW',
@article = N'tab1',
@source_owner = N'dbo',
@source_object = N'tab1',
@type = N'logbased',
@description = NULL,
@creation_script = NULL,
@pre_creation_cmd = N'drop',
@schema_option = 0x0000000008035DDB,
@identityrangemanagementoption = N'manual',
@destination_table = N'tab1',
@destination_owner = N'dbo',
@status = 16,
@vertical_partition = N'false',
@ins_cmd = N'CALL sp_MSins_dbotab1',
@del_cmd = N'CALL sp_MSdel_dbotab1',
@upd_cmd = N'CALL sp_MSupd_dbotab1';
GO
Criar publicação no segundo par (Node2)
O script a seguir cria a publicação no segundo par (Nó 2).
USE [MWPubDB];
EXECUTE sp_replicationdboption
@dbname = N'MWPubDB',
@optname = N'publish',
@value = N'true';
GO
-- Adding the transactional publication
USE [MWPubDB];
EXECUTE sp_addpublication
@publication = N'PublMW',
@description = N'Peer-to-Peer publication of database ''MWPubDB'' from Publisher ''Node2''.',
@sync_method = N'native',
@retention = 0,
@allow_push = N'true',
@allow_pull = N'true',
@allow_anonymous = N'false',
@enabled_for_internet = N'false',
@snapshot_in_defaultfolder = N'true',
@compress_snapshot = N'false',
@ftp_port = 21,
@allow_subscription_copy = N'false',
@add_to_active_directory = N'false',
@repl_freq = N'continuous',
@status = N'active',
@independent_agent = N'true',
@immediate_sync = N'true',
@allow_sync_tran = N'false',
@allow_queued_tran = N'false',
@allow_dts = N'false',
@replicate_ddl = 1,
@allow_initialize_from_backup = N'true',
@enabled_for_p2p = N'true',
@enabled_for_het_sub = N'false',
@p2p_conflictdetection = N'true',
@p2p_originator_id = 1,
@p2p_continue_onconflict = 'true',
@p2p_conflictdetection_policy = 'lastwriter';
GO
USE [MWPubDB];
EXECUTE sp_addarticle
@publication = N'PublMW',
@article = N'tab1',
@source_owner = N'dbo',
@source_object = N'tab1',
@type = N'logbased',
@description = NULL,
@creation_script = NULL,
@pre_creation_cmd = N'drop',
@schema_option = 0x0000000008035DDB,
@identityrangemanagementoption = N'manual',
@destination_table = N'tab1',
@destination_owner = N'dbo',
@status = 16,
@vertical_partition = N'false',
@ins_cmd = N'CALL sp_MSins_dbotab1',
@del_cmd = N'CALL sp_MSdel_dbotab1',
@upd_cmd = N'CALL sp_MSupd_dbotab1';
GO
Criar assinatura do Node1 para o Node2
USE [MWPubDB];
EXECUTE sp_addsubscription
@publication = N'PublMW',
@subscriber = N'Node2',
@destination_db = N'MWPubDB',
@subscription_type = N'Push',
@sync_type = N'replication support only',
@article = N'all',
@update_mode = N'read only',
@subscriber_type = 0;
GO
EXECUTE sp_addpushsubscription_agent
@publication = N'PublMW',
@subscriber = N'Node2',
@subscriber_db = N'MWPubDB',
@job_login = NULL,
@job_password = NULL,
@subscriber_security_mode = 1,
@frequency_type = 64,
@frequency_interval = 1,
@frequency_relative_interval = 1,
@frequency_recurrence_factor = 0,
@frequency_subday = 4,
@frequency_subday_interval = 5,
@active_start_time_of_day = 0,
@active_end_time_of_day = 235959,
@active_start_date = 0,
@active_end_date = 0,
@dts_package_location = N'Distributor';
GO
Criar assinatura do Node2 para o Node1
USE [MWPubDB];
EXECUTE sp_addsubscription
@publication = N'PublMW',
@subscriber = N'Node1',
@destination_db = N'MWPubDB',
@subscription_type = N'Push',
@sync_type = N'replication support only',
@article = N'all',
@update_mode = N'read only',
@subscriber_type = 0;
GO
EXECUTE sp_addpushsubscription_agent
@publication = N'PublMW',
@subscriber = N'Node1',
@subscriber_db = N'MWPubDB',
@job_login = NULL,
@job_password = NULL,
@subscriber_security_mode = 1,
@frequency_type = 64,
@frequency_interval = 1,
@frequency_relative_interval = 1,
@frequency_recurrence_factor = 0,
@frequency_subday = 4,
@frequency_subday_interval = 5,
@active_start_time_of_day = 0,
@active_end_time_of_day = 235959,
@active_start_date = 0,
@active_end_date = 0,
@dts_package_location = N'Distributor';
GO