Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Från och med SQL Server 2019 (15.x) CU13 kan du konfigurera peer-to-peer-replikering för att automatiskt lösa konflikter genom att tillåta att den senaste infogningen eller uppdateringen vinner konflikten. Om någon av skrivningarna tar bort raden tillåter SQL Server att borttagningen vinner konflikten. Den här metoden kallas för senaste skrivningsvinster.
Använd lagrade procedurer för att konfigurera senaste skrivvinster. Använd inte guiden Peer-to-Peer-topologi för att lägga till eller ta bort noder när du använder den senaste skrivaren.
Viktiga konfigurationsöverväganden
Anmärkning
När du har uppdaterat till SQL Server 2019 (15.x) CU13 eller en senare version inkluderas extra metadata i publikationen när du konfigurerar en publikation med konfliktlösning inställd på senaste skrivvinster. Om du senare avinstallerar/nedgraderar till en tidigare version än SQL Server 2019 (15.x) CU13 orsakar dessa extra metadata problem. Du bör ta bort sådana publikationer innan du nedgraderar och sedan återskapa dem på den lägre versionen.
När du konfigurerar peer-to-peer-replikering med automatisk konfliktidentifiering och lösning för att lösa som senaste skrivvinster ska du inkludera följande konfigurationer och inställningar:
Skapa publikationen med följande parametrar:
Ange
@p2p_conflictdetection_policy = 'lastwriter'för att ange senaste skrivningsvinster. Se sp_addpublication (Transact-SQL). Den här parametern introduceras i SQL Server 2019 (15.x) CU13. Standardvärdetoriginatoridlöser konflikter baserat på ursprungs-ID:t och är detsamma som konfliktlösning före SQL Server 2019 (15.x) CU13.Ange
@p2p_continue_onconflict = 'true'så att distributionsagenten kan lösa konflikten.
När du lägger till artikeln (
sp_addarticle) bekräftar du beteendet för kommandotypen för uppdateringskommandot (@upd_cmd). Alternativen inkluderar:-
CALL(Standard) SCALL
Se information i sp_addarticle.
-
När du lägger till en artikel (
sp_addarticle) i en publikation med en princip för senaste konfliktidentifiering för skrivare är användningCALLellerSCALLsom kommandotyp för@upd_cmdparameterCALLstandard.Anmärkning
SQL Server stöder
SCALLför@upd_cmd. NärSCALLen transaktion uppdaterar ett värde till samma värde betraktas det inte som en ändring ochSCALLformatet anger inte värdet för kolumner som inte uppdateras eller ändras. Mer information om SCALL-samtalsformat finns i Samtalssyntax för lagrade procedurer.Du kan använda peer-to-peer-publikation med senaste konfliktidentifiering och lösning för skrivare i en tillgänglighetsgrupp. See:
Du kan se konflikten och dess lösning.
- Högerklicka på publikationen i SQL Server Management Studio och välj Visa konflikter.
Eller
- Fråga
conflict_schemaname_tablenamei publikationsdatabasen. Till exempelconflict_dbo_tab1. Se conflict_<schema>_<table> (Transact-SQL).
Infognings- och uppdateringskonflikter löses baserat på den senaste skrivaren, men borttagningen gäller alltid. Om du till exempel har en konflikt med borttagningsuppdateringen och uppdateringen gjordes vid ett senare tillfälle vinner fortfarande borttagningen.
Identifiering och lösning av den senaste skrivkonflikten bestäms baserat på en dold kolumn
$sys_mw_cd_id. Datatypen för den här kolumnen är datetime2.
Jämförelse av konfliktidentifiering
I följande tabell jämförs hur konflikter identifieras och löses med traditionell peer-to-peer-replikering och när den senaste konfliktlösningen för skrivare är aktiverad:
| Konflikttyp | Konfliktinformation | Peer-to-peer | Senaste skribent |
|---|---|---|---|
| Insert-Insert | Alla rader i varje tabell som deltar i peer-to-peer-replikering identifieras unikt med hjälp av primärnyckelvärden. En infogningskonflikt uppstår när en rad med samma nyckelvärde infogades på mer än en nod. | Om den inkommande raden är vinnaren uppdaterar vi målraden. I båda fallen registrerar vi informationen. | Om den inkommande raden är vinnaren uppdaterar vi målraden. I båda fallen registrerar vi informationen. |
| Update-Update | Inträffar när samma rad uppdaterades på mer än en nod. | Om den inkommande raden är vinnaren ändrar vi ENDAST de ändrade kolumnerna. | Om den inkommande raden är vinnaren ändrar vi alla kolumner på målet (om @upd_cmd är inställt default på – CALL). |
| Update-Insert | Inträffar om en rad uppdaterades på en nod, men samma rad togs bort och sedan återansluts på en annan nod. | Om den inkommande raden är vinnaren ändrar vi ENDAST de ändrade kolumnerna. | Detta inträffar när en rad uppdateras på peer1 och samma rad tas bort och sätts tillbaka på peer2. När synkroniseringen sker tas raden på peer1 bort eftersom borttagningen alltid vinner och sedan infogas samma rad, medan raden uppdateras peer2 när den uppdateras vid ett senare tillfälle. Detta leder till icke-konvergering. |
| Infoga – Uppdatera | Inträffar om en rad har tagits bort och sedan har återanslutit vid en nod och samma rad har uppdaterats på en annan nod. | Om den inkommande raden är vinnaren uppdaterar vi alla kolumner. | Detta inträffar när en rad tas bort och sätts på igen peer1 och samma rad uppdateras på peer2. När synkroniseringen sker tas raden bort eftersom peer2 borttagningen alltid vinner och sedan infogas den igen. På peer1hoppas uppdateringen över. |
| Delete-Insert Insert-Delete |
Inträffar om en rad har tagits bort på en nod, men samma rad har tagits bort och sedan återansluts till en annan nod. | Vi tror för närvarande att detta är en D-U-konflikt och om den inkommande raden sedan är vinnare tar vi bort raden från målet. | Detta inträffar när en rad tas bort på peer1 och samma rad tas bort + sätts tillbaka på peer2. När synkroniseringen sker tas raden på peer2 bort, medan raden infogas på peer1. Detta beror på att vi inte lagrar information om den borttagna raden, så vi vet inte om raden har tagits bort eller inte fanns på peer-filen. Detta leder till icke-konvergering. |
| Delete-Update | Inträffar om en rad har tagits bort på en nod, men samma rad har uppdaterats på en annan nod. | Vi tror för närvarande att detta är en D-U-konflikt och om den inkommande raden är vinnaren tar vi bort raden från målet. | Det här är en D-U-konflikt. Eftersom borttagning alltid vinner är inkommande borttagning vinnaren och vi tar bort raden från målet. |
| Update-Delete | Inträffar om en rad uppdaterades på en nod, men samma rad togs bort på en annan nod. | Om det finns en UD-konflikt i den lagrade proceduren peer-to-peer Update skriver vi ut följande meddelande och löser det inte.An update-delete conflict was detected and unresolved. The row could not be updated since the row does not exist. |
Det här är en U-D-konflikt. När borttagningen alltid vinner hoppas den inkommande uppdateringen över. |
| Delete-Delete | Inträffar när en rad har tagits bort på mer än en nod. | Om det finns en D-D-konflikt i den lagrade proceduren peer-to-peer Ta bort bearbetar vi inte någon ändring, utan registrerar den bara. | Om det finns en D-D-konflikt bearbetar vi inte någon ändring, bara registrerar den. |
Anmärkning
I den aktuella implementeringen av den senaste konfliktidentifieringsprincipen för skrivare vinner alltid borttagningen när det finns en konflikt mellan infoga, ta bort eller ta bort.
Examples
Skapa publikation på första peer (Node1)
I det här exemplet skriptet:
- Publicerar en databas med namnet
MWPubDB. - Namnger publikationen
PublMW. - Konfigurerar konfliktidentifiering och lösningsprincip som senaste skrivvinster:
, @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
Skapa publikation på andra peer (Node2)
Följande skript skapar publikationen på den andra peer-datorn (nod 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
Skapa prenumeration från Node1 till 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
Skapa prenumeration från Node2 till 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