Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
A partire da SQL Server 2019 (15.x) CU13, è possibile configurare la replica peer-to-peer per risolvere automaticamente i conflitti consentendo l'inserimento o l'aggiornamento più recente per vincere il conflitto. Se una delle due scritture elimina la riga, SQL Server fa prevalere l'eliminazione nel conflitto. Questo metodo è noto come “l'ultima scrittura prevale”.
Usa le stored procedure per configurare il criterio in base al quale prevale l'ultima scrittura. Non usare la procedura guidata topologia peer-to-peer per aggiungere o rimuovere nodi quando si usa l'ultimo writer.
Considerazioni importanti sulla configurazione
Annotazioni
Dopo l'aggiornamento a SQL Server 2019 (15.x) CU13 o versione successiva, quando si configura una pubblicazione con risoluzione dei conflitti impostata sull'ultima vittoria di scrittura, nella pubblicazione vengono inclusi metadati aggiuntivi. Se in seguito si disinstalla/effettua il downgrade a una versione precedente a SQL Server 2019 (15.x) CU13, questi metadati aggiuntivi causano problemi. È consigliabile eliminare tali pubblicazioni prima del downgrade e quindi ricrearle nella versione precedente.
Quando si configura la replica peer-to-peer con rilevamento e risoluzione automatica dei conflitti, con risoluzione basata sull'ultima scrittura, includere le configurazioni e le impostazioni seguenti:
Creare la pubblicazione con i parametri seguenti:
Impostare
@p2p_conflictdetection_policy = 'lastwriter'per specificare che l'ultima scrittura ha la precedenza. Vedere sp_addpublication (Transact-SQL). Questo parametro è stato introdotto in SQL Server 2019 (15.x) CU13. Il valoreoriginatoridpredefinito risolve i conflitti in base all'ID origine e corrisponde alla risoluzione dei conflitti prima di SQL Server 2019 (15.x) CU13.Impostare
@p2p_continue_onconflict = 'true'per consentire all'agente di distribuzione di risolvere il conflitto.
Quando si aggiunge l'articolo (
sp_addarticle), verificare il comportamento del tipo di comando per il comando update (@upd_cmd). Le opzioni includono:-
CALL(Impostazione predefinita) SCALL
Vedere i dettagli in sp_addarticle.
-
Quando si aggiunge un articolo (
sp_addarticle) in una pubblicazione con un criterio di rilevamento dei conflitti dell'ultimo autore, utilizzareCALLoSCALLcome tipo di comando per il parametro@upd_cmd;CALLè l'impostazione predefinita.Annotazioni
SQL Server supporta
SCALLper@upd_cmd. ConSCALL, quando una transazione aggiorna un valore allo stesso valore, non viene considerato come una modifica eSCALLil formato non fornisce il valore per le colonne che non vengono aggiornate o modificate. Per altre informazioni sul formato di chiamata SCALL, vedere Sintassi delle chiamate per le stored procedure.È possibile utilizzare la pubblicazione peer-to-peer con il rilevamento e la risoluzione dei conflitti in base all'ultimo autore di scrittura in un gruppo di disponibilità. See:
È possibile visualizzare il conflitto e la relativa risoluzione.
- In SQL Server Management Studio fare clic con il pulsante destro del mouse sulla pubblicazione e scegliere Visualizza conflitti.
oppure
- Interroga
conflict_schemaname_tablenamenel database delle pubblicazioni. Ad esempio:conflict_dbo_tab1. Vedere conflict_<schema>_<table> (Transact-SQL).
I conflitti di inserimento e aggiornamento vengono risolti in base all'ultima scrittura, ma l'eliminazione prevale sempre. Ad esempio, se si verifica un conflitto di eliminazione-aggiornamento e l'aggiornamento è stato eseguito in un secondo momento, l'eliminazione continua a prevalere.
Il rilevamento e la risoluzione dei conflitti dell'ultimo writer sono determinati in base a una colonna
$sys_mw_cd_idnascosta. Il tipo di dati di questa colonna è datetime2.
Confronto del rilevamento dei conflitti
La tabella seguente confronta il modo in cui i conflitti vengono rilevati e risolti con la replicazione peer-to-peer tradizionale e quando è abilitata la risoluzione dei conflitti in base all'ultima scrittura:
| Tipo di conflitto | Dettagli del conflitto | Peer-to-peer | Ultimo autore |
|---|---|---|---|
| Inserisci-Inserisci | Tutte le righe di ogni tabella che partecipano alla replica peer-to-peer vengono identificate in modo univoco usando i valori di chiave primaria. Un conflitto insert-insert si verifica quando la stessa riga con lo stesso valore della chiave è stata inserita in più di un nodo. | Se la riga in ingresso è il vincitore, aggiorniamo la riga di destinazione. In entrambi i casi, le informazioni vengono registrate. | Se la riga in ingresso è il vincitore, aggiorniamo la riga di destinazione. In entrambi i casi, le informazioni vengono registrate. |
| Aggiornamento-Aggiornamento | Si verifica quando la stessa riga è stata aggiornata in più nodi. | Se la riga in arrivo è quella vincente, vengono modificate solo le colonne cambiate. | Se la riga in ingresso è il vincitore, si modificano tutte le colonne nella destinazione (se @upd_cmd è impostata su default – CALL). |
| Aggiorna-Inserisci | Si verifica se una riga è stata aggiornata in un nodo, ma la stessa riga è stata eliminata e quindi reinsertata in un altro nodo. | Se la riga in entrata risulta vincente, vengono modificate solo le colonne modificate. | Ciò si verifica quando una riga viene aggiornata in peer1 e la stessa riga viene eliminata e reinsertata in peer2. Quando si verifica la sincronizzazione, la riga su peer1 viene eliminata, poiché l'eliminazione prevale sempre, e poi la stessa riga viene inserita nuovamente, mentre la riga su peer2 viene aggiornata, poiché l'aggiornamento è avvenuto in un momento successivo. Questo porta alla nonconvergenza. |
| Inserisci - Aggiorna | Si verifica se una riga è stata eliminata e quindi reinsertata in un nodo e la stessa riga è stata aggiornata in un altro nodo. | Se la riga in ingresso è il vincitore, aggiorniamo tutte le colonne. | Ciò si verifica quando una riga viene eliminata e reinsertata in peer1 e la stessa riga viene aggiornata in peer2. Quando si verifica la sincronizzazione, la riga viene eliminata su peer2, poiché l'eliminazione ha sempre la precedenza, e quindi viene inserita nuovamente. In peer1l'aggiornamento viene ignorato. |
| Elimina-Inserisci Inserisci-Elimina |
Si verifica se una riga è stata eliminata in un nodo, ma la stessa riga è stata eliminata e quindi reinsertata in un altro nodo. | Attualmente consideriamo questo caso come un conflitto D-U e, se la riga in ingresso risulta vincitrice, eliminiamo la riga dalla destinazione. | Ciò si verifica quando una riga viene eliminata in peer1 e la stessa riga viene eliminata + reinsertata in peer2. Quando si verifica la sincronizzazione, la riga su peer2 viene eliminata, mentre la riga viene inserita in peer1. Ciò si verifica perché non vengono archiviate informazioni sulla riga eliminata, quindi non si sa se la riga è stata eliminata o non è stata presente nel peer. Questo porta alla nonconvergenza. |
| Eliminazione-Aggiornamento | Si verifica se una riga è stata eliminata in un nodo, ma la stessa riga è stata aggiornata in un altro nodo. | Al momento lo consideriamo un conflitto D-U e, se la riga in arrivo risulta vincente, eliminiamo la riga dalla destinazione. | Questo è un conflitto tra D e U. Poiché l'eliminazione ha sempre la precedenza, la richiesta di eliminazione in ingresso prevale ed eliminiamo la riga nella destinazione. |
| Aggiorna-Elimina | Si verifica se una riga è stata aggiornata in un nodo, ma la stessa riga è stata eliminata in un altro nodo. | Nella procedura memorizzata di aggiornamento peer-to-peer, se si verifica un conflitto U-D, viene stampato il messaggio seguente e il conflitto non viene risolto.An update-delete conflict was detected and unresolved. The row could not be updated since the row does not exist. |
Questo è un conflitto U-D. Poiché l'operazione di eliminazione ha sempre la precedenza, l'aggiornamento in arrivo viene ignorato. |
| Elimina-Elimina | Si verifica quando una riga è stata eliminata in più nodi. | Nella stored procedure Delete peer-to-peer, se si verifica un conflitto D-D, non elaboriamo alcuna modifica, ci limitiamo solo a registrarla. | Se si verifica un conflitto D-D, non viene elaborata alcuna modifica, è sufficiente registrarla. |
Annotazioni
Nell'implementazione corrente del criterio di rilevamento dei conflitti dell'ultima scrittura, l'eliminazione ha sempre la precedenza quando si verifica un conflitto di tipo inserimento-eliminazione, eliminazione-inserimento o aggiornamento-eliminazione.
Esempi
Creare una pubblicazione nel primo peer (Node1)
In questo esempio lo script:
- Pubblica un database denominato
MWPubDB. - Denomina la pubblicazione
PublMW. - Configura i criteri di rilevamento e risoluzione dei conflitti come ultima scrittura vince:
, @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
Creare una pubblicazione nel secondo peer (Node2)
Lo script seguente crea la pubblicazione nel secondo peer (Nodo 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
Creare una sottoscrizione da Node1 a 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
Creare una sottoscrizione da Node2 a 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
Contenuti correlati
- Peer-to-Peer - Rilevamento dei conflitti nella replicazione Peer-to-Peer
- Articoli transazionali: specificare la modalità di propagazione delle modifiche
- sys.sp_addpublication (Transact-SQL)
- Configurare un peer come parte di un gruppo di disponibilità
- Configurare entrambi i peer nei gruppi di disponibilità