Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Comprensione dei conflitti attivi-attivi
Quando usi pgactive in modalità active-active, la scrittura sulle stesse tabelle da più nodi può creare conflitti di dati. Sebbene alcuni sistemi di clustering utilizzino blocchi distribuiti per impedire l'accesso simultaneo, pgactive adotta un approccio ottimistico più adatto per applicazioni distribuite geograficamente.
Alcuni sistemi di clustering di database impediscono l'accesso simultaneo ai dati utilizzando blocchi distribuiti. Sebbene questo approccio funzioni quando i server sono nelle immediate vicinanze, non supporta applicazioni distribuite geograficamente perché richiede una latenza estremamente bassa per ottenere buone prestazioni. Invece di utilizzare blocchi distribuiti (un approccio pessimista), l'estensione pgactive utilizza un approccio ottimistico. Ciò significa che:
-
Ti aiuta a evitare i conflitti quando possibile.
-
Consente il verificarsi di determinati tipi di conflitti.
-
Fornisce la risoluzione dei conflitti quando si verificano conflitti.
Questo approccio offre una maggiore flessibilità nella creazione di applicazioni distribuite.
Come avvengono i conflitti
I conflitti tra nodi derivano da sequenze di eventi che non potrebbero verificarsi se tutte le transazioni coinvolte avvenissero contemporaneamente sullo stesso nodo. Poiché i nodi scambiano le modifiche solo dopo il completamento delle transazioni, ogni transazione è valida individualmente sul nodo su cui è stata effettuata l'esecuzione, ma non lo sarebbe se eseguita su un altro nodo che nel frattempo ha svolto altre operazioni. Poiché pgactive apply essenzialmente riproduce la transazione sugli altri nodi, l'operazione di replay può fallire in caso di conflitto tra una transazione applicata e una transazione che è stata confermata sul nodo ricevente.
Il motivo per cui la maggior parte dei conflitti non può verificarsi quando tutte le transazioni vengono eseguite su un singolo nodo è che PostgreSQL dispone di meccanismi di comunicazione tra transazioni per prevenirli, tra cui:
-
Indici UNIQUE
-
SEQUENCEs
-
Blocco di righe e relazioni
-
Monitoraggio delle dipendenze SERIALIZABLE
Tutti questi meccanismi sono modi per comunicare tra le transazioni per prevenire problemi di concorrenza indesiderati
pgactive raggiunge una bassa latenza e gestisce bene le partizioni di rete perché non utilizza un gestore di transazioni distribuito o un gestore di blocchi. Tuttavia, ciò significa che le transazioni su nodi diversi vengono eseguite in completo isolamento l'una dall'altra. Sebbene l'isolamento in genere migliori la coerenza del database, in questo caso è necessario ridurre l'isolamento per prevenire i conflitti.
Tipi di conflitti
I conflitti che possono verificarsi includono:
Argomenti
conflitti PRIMARY KEY o UNIQUE
I conflitti di riga si verificano quando più operazioni tentano di modificare la stessa chiave di riga in modi non possibili su un singolo nodo. Questi conflitti rappresentano il tipo più comune di conflitti di dati.
pgactive risolve i conflitti rilevati tramite la last-update-wins gestione o il gestore dei conflitti personalizzato.
I conflitti di riga includono:
-
INSERT e INSERT
-
INSERT vs UPDATE
-
AGGIORNA vs ELIMINA
-
INSERT vs DELETE
-
ELIMINA vs ELIMINA
-
INSERT vs DELETE
Conflitti INSERT/INSERT
Questo conflitto più comune si verifica quando INSERTs su due nodi diversi si crea una tupla con gli stessi valori PRIMARY KEY (o valori di vincolo UNIQUE identici quando non esiste una CHIAVE PRIMARIA).
pgactivelink risolve i conflitti INSERT utilizzando il timestamp dell'host di origine per mantenere la tupla più recente. Puoi sovrascrivere questo comportamento predefinito con il tuo gestore di conflitti personalizzato. Sebbene questo processo non richieda alcuna azione speciale dell'amministratore, tieni presente che pgactivelink scarta una delle operazioni INSERT su tutti i nodi. Non si verifica alcuna unione automatica dei dati a meno che il gestore personalizzato non la implementi.
Il pgactivelink può risolvere solo i conflitti che coinvolgono una singola violazione del vincolo. Se un INSERT viola più vincoli UNIQUE, è necessario implementare ulteriori strategie di risoluzione dei conflitti.
INSERTsche violano più vincoli UNIQUE
Un conflitto INSERT/INSERT può violare più vincoli UNIQUE, inclusa la CHIAVE PRIMARIA. pgactivelink può gestire solo i conflitti che coinvolgono un singolo vincolo UNIQUE. Quando i conflitti violano più vincoli UNIQUE, l'application worker fallisce e restituisce il seguente errore:
multiple unique constraints violated by remotely INSERTed tuple.
Nelle versioni precedenti, questa situazione generava invece un errore di «conflitto di unicità divergente».
Per risolvere questi conflitti, è necessario intraprendere un'azione manuale. ELIMINA le tuple locali in conflitto o AGGIORNALE per rimuovere i conflitti con la nuova tupla remota. Tieni presente che potresti dover risolvere più tuple in conflitto. Attualmente, pgactivelink non fornisce alcuna funzionalità integrata per ignorare, scartare o unire tuple che violano più vincoli unici.
Nota
Per ulteriori informazioni, vedi che violano più vincoli UNIQUE. UPDATEs
Conflitti di aggiornamento/aggiornamento
Questo conflitto si verifica quando due nodi modificano contemporaneamente la stessa tupla senza cambiarne la CHIAVE PRIMARIA. pgactivelink risolve questi conflitti utilizzando la logica o il gestore dei conflitti personalizzato, se definito. last-update-wins Una CHIAVE PRIMARIA è essenziale per la corrispondenza delle tuple e la risoluzione dei conflitti. Per le tabelle senza una CHIAVE PRIMARIA, pgactivelink rifiuta le operazioni UPDATE con il seguente errore:
Cannot run UPDATE or DELETE on table (tablename) because it does not have a
primary key.
UPDATE è in conflitto sulla CHIAVE PRIMARIA
pgactive presenta delle limitazioni nella gestione degli aggiornamenti della CHIAVE PRIMARIA. Sebbene sia possibile eseguire l'operazione UPDATE su una CHIAVE PRIMARIA, pgactive non può risolvere automaticamente i conflitti utilizzando la last-update-wins logica per queste operazioni. È necessario assicurarsi che gli aggiornamenti della CHIAVE PRIMARIA non siano in conflitto con i valori esistenti. Se si verificano conflitti durante gli aggiornamenti della CHIAVE PRIMARIA, diventano conflitti divergenti che richiedono l'intervento manuale dell'utente. Per ulteriori informazioni sulla gestione di queste situazioni, vedere. Conflitti divergenti
UPDATEsche violano più vincoli UNIQUE
pgactivelink non può applicare la risoluzione dei last-update-wins conflitti quando un UPDATE in entrata viola più vincoli UNIQUE o valori PRIMARY KEY. Questo comportamento è simile alle operazioni INSERT con più violazioni dei vincoli. Queste situazioni creano conflitti divergenti che richiedono l'intervento manuale dell'utente. Per ulteriori informazioni, consulta Conflitti divergenti.
Conflitti di aggiornamento/eliminazione
Questi conflitti si verificano quando un nodo è UPDATEs una riga e un altro nodo contemporaneamente. DELETEs In questo caso si verifica un conflitto UPDATE/DELETE durante la riproduzione. La soluzione consiste nell'eliminare qualsiasi UPDATE che arriva dopo un DELETE, a meno che il gestore dei conflitti personalizzato non specifichi diversamente.
pgactivelink richiede una CHIAVE PRIMARIA per abbinare le tuple e risolvere i conflitti. Per le tabelle senza una CHIAVE PRIMARIA, rifiuta le operazioni DELETE con il seguente errore:
Cannot run UPDATE or DELETE on table (tablename) because it does not have a
primary key.
Nota
pgactivelink non è in grado di distinguere tra conflitti. UPDATE/DELETE and INSERT/UPDATE In entrambi i casi, un UPDATE influisce su una riga inesistente. A causa della replica asincrona e della mancanza di un ordine di riproduzione tra i nodi, pgactivelink non è in grado di determinare se l'UPDATE si riferisce a una nuova riga (INSERT non ancora ricevuto) o a una riga eliminata. In entrambi gli scenari, pgactivelink elimina l'UPDATE.
Conflitti di inserimento/aggiornamento
Questo conflitto può verificarsi in ambienti con più nodi. Si verifica quando INSERTs un nodo per riga, un secondo nodo UPDATEs e un terzo nodo ricevono l'UPDATE prima dell'INSERT originale. Per impostazione predefinita, pgactivelink risolve questi conflitti eliminando l'UPDATE, a meno che il trigger di conflitto personalizzato non specifichi diversamente. Tieni presente che questo metodo di risoluzione può causare incongruenze nei dati tra i nodi. Per ulteriori informazioni su scenari simili e sulla loro gestione, consulta. Conflitti di aggiornamento/eliminazione
ELIMINA/ELIMINA i conflitti
Questo conflitto si verifica quando due nodi diversi eliminano contemporaneamente la stessa tupla. pgactivelink considera questi conflitti innocui perché entrambe le operazioni DELETE hanno lo stesso risultato finale. In questo scenario, pgactivelink ignora in modo sicuro una delle operazioni DELETE senza influire sulla coerenza dei dati.
Conflitti di vincoli di chiave esterna
I vincoli FOREIGN KEY possono causare conflitti quando si applicano transazioni remote a dati locali esistenti. Questi conflitti si verificano in genere quando le transazioni vengono applicate in una sequenza diversa rispetto al loro ordine logico sui nodi di origine.
Per impostazione predefinita, pgactive applica le modifiche con session_replication_role asreplica
, che ignora i controlli delle chiavi esterne durante la replica. Nelle configurazioni active-active, ciò può portare a violazioni di chiavi esterne. La maggior parte delle violazioni sono temporanee e si risolvono una volta ripristinata la replica. Tuttavia, possono verificarsi chiavi esterne sospese perché pgactive non supporta il blocco delle righe tra nodi.
Questo comportamento è inerente ai sistemi asincroni attivi-attivi asincroni tolleranti alle partizioni. Ad esempio, il nodo A potrebbe inserire una nuova riga secondaria mentre il nodo B elimina contemporaneamente la riga principale. Il sistema non può impedire questo tipo di modifica simultanea tra i nodi.
Per ridurre al minimo i conflitti tra chiavi esterne, consigliamo quanto segue:
-
Limita le relazioni con chiave esterna a entità strettamente correlate.
-
Modifica le entità correlate da un singolo nodo quando possibile.
-
Scegliete entità che raramente richiedono modifiche.
-
Implementa il controllo della concorrenza a livello di applicazione per le modifiche.
Conflitti tra vincoli di esclusione
pgactive link non supporta i vincoli di esclusione e ne limita la creazione.
Nota
Se converti un database autonomo esistente in un database pgactivelink, elimina manualmente tutti i vincoli di esclusione.
In un sistema asincrono distribuito, non è possibile garantire che nessun insieme di righe violi il vincolo. Questo perché tutte le transazioni su nodi diversi sono completamente isolate. I vincoli di esclusione possono portare a situazioni di stallo di riproduzione, in cui la riproduzione non può passare da un nodo all'altro a causa delle violazioni dei vincoli di esclusione.
Se imponi a pgactive Link di creare un vincolo di esclusione o se non elimini quelli esistenti durante la conversione di un database autonomo in pgactive Link, è probabile che la replica si interrompa. Per ripristinare l'avanzamento della replica, rimuovi o modifica le tuple locali in conflitto con una tupla remota in entrata in modo da poter applicare la transazione remota.
Conflitti globali di dati
Quando si utilizza pgactivelink, possono verificarsi conflitti quando i nodi hanno dati globali diversi a livello di sistema PostgreSQL, come i ruoli. Questi conflitti possono causare il successo e il commit delle operazioni, principalmente DDL, su un nodo, ma non possono essere applicate agli altri nodi.
Se un utente esiste su un nodo ma non su un altro, possono verificarsi problemi di replica:
-
Node1 ha un utente denominato
fred
, ma questo utente non esiste su Node2 -
Quando si
fred
crea una tabella su Node1, la tabella viene replicata con il nome di proprietariofred
-
Quando questo comando DDL viene applicato a Node2, fallisce perché l'utente non esiste
fred
-
Questo errore genera un ERRORE nei log PostgreSQL su Node2 e incrementa il contatore
pgactive.pgactive_stats.nr_rollbacks
Risoluzione: crea l'utente su Node2. fred
L'utente non necessita di autorizzazioni identiche ma deve esistere su entrambi i nodi.
Se una tabella esiste su un nodo ma non su un altro, le operazioni di modifica dei dati falliranno:
-
Node1 ha una tabella denominata
foo
che non esiste in Node2 -
Qualsiasi operazione DML sulla
foo
tabella su Node1 avrà esito negativo se replicata su Node2
Risoluzione: crea la tabella foo
su Node2 con la stessa struttura.
Nota
pgactivelink attualmente non replica i comandi CREATE USER o le operazioni DDL. La replica DDL è prevista per le future release.
Blocca i conflitti e le interruzioni in fase di stallo
Poiché i processi di applicazione di pgactive funzionano come normali sessioni utente, seguono le regole standard di blocco delle righe e delle tabelle. Ciò può far sì che i processi di applicazione di pgactivelink restino bloccati dalle transazioni degli utenti o da altri processi di applicazione.
I seguenti tipi di blocchi possono influire sui processi di applicazione:
-
Blocco esplicito a livello di tabella (LOCK TABLE...) da parte delle sessioni utente
-
Blocco esplicito a livello di riga (SELECT... FOR UPDATE/FOR SHARE) per sessioni utente
-
Blocco da chiavi esterne
-
Blocco implicito dovuto alla riga UPDATEs o DELETEs all'attività locale o applicato da altri server INSERTs
I deadlock possono verificarsi tra:
-
Un processo di applicazione pgactivelink e una transazione utente
-
Due processi di applicazione
Quando si verificano dei deadlock, il deadlock detector di PostgreSQL interrompe una delle transazioni problematiche. Se il processo del worker di applicazione pgactivelink viene terminato, riprova automaticamente e in genere riesce.
Nota
-
Questi problemi sono temporanei e generalmente non richiedono l'intervento dell'amministratore. Se un processo di applicazione viene bloccato per un periodo prolungato a causa del blocco di una sessione utente inattiva, è possibile interrompere la sessione utente per riprendere la replica. Questa situazione è simile a quando un utente mantiene un blocco lungo che influisce su un'altra sessione utente.
-
Per identificare i ritardi di riproduzione legati al blocco, abilita la funzione in PostgreSQL.
log_lock_waits
Conflitti divergenti
I conflitti divergenti si verificano quando i dati che dovrebbero essere identici tra i nodi differiscono in modo imprevisto. Sebbene questi conflitti non dovrebbero verificarsi, non tutti possono essere evitati in modo affidabile con l'implementazione attuale.
Nota
La modifica della CHIAVE PRIMARIA di una riga può causare conflitti divergenti se un altro nodo modifica la chiave della stessa riga prima che tutti i nodi elaborino la modifica. Evita di modificare le chiavi primarie o limita le modifiche a un nodo designato. Per ulteriori informazioni, consulta UPDATE è in conflitto sulla CHIAVE PRIMARIA .
I conflitti divergenti che coinvolgono i dati delle righe richiedono in genere l'intervento dell'amministratore. Per risolvere questi conflitti, è necessario modificare manualmente i dati su un nodo in modo che corrispondano a un altro, disabilitando temporaneamente la replica utilizzando. pgactive.pgactive_do_not_replicate
Questi conflitti non dovrebbero verificarsi quando si utilizza pgactive come documentato ed evitare impostazioni o funzioni contrassegnate come non sicure.
In qualità di amministratore, devi risolvere manualmente questi conflitti. A seconda del tipo di conflitto, dovrai utilizzare opzioni avanzate comepgactive.pgactive_do_not_replicate
. Usa queste opzioni con cautela, poiché un uso improprio può peggiorare la situazione. A causa della varietà di possibili conflitti, non possiamo fornire istruzioni universali per la risoluzione.
I conflitti divergenti si verificano quando dati che dovrebbero essere identici su nodi diversi differiscono inaspettatamente. Sebbene questi conflitti non dovrebbero verificarsi, non tutti possono essere evitati in modo affidabile nell'attuale implementazione.
Evitare o tollerare i conflitti
Nella maggior parte dei casi, è possibile utilizzare un design appropriato dell'applicazione per evitare conflitti o rendere l'applicazione tollerante nei confronti dei conflitti.
I conflitti si verificano solo quando le operazioni simultanee avvengono su più nodi. Per evitare conflitti:
-
Scrivi su un solo nodo
-
Scrivi su sottoinsiemi di database indipendenti su ogni nodo (ad esempio, assegna a ogni nodo uno schema separato)
Per i conflitti INSERT e INSERT, utilizzate le sequenze Global per prevenire completamente i conflitti.
Se i conflitti non sono accettabili per il vostro caso d'uso, prendete in considerazione l'implementazione del blocco distribuito a livello di applicazione. Spesso, l'approccio migliore è quello di progettare l'applicazione in modo che funzioni con i meccanismi di risoluzione dei conflitti di pgactive piuttosto che cercare di prevenire tutti i conflitti. Per ulteriori informazioni, consulta Tipi di conflitti.
Registrazione dei conflitti
pgactivelink registra gli incidenti di conflitto nella pgactive.pgactive_conflict_history
tabella per aiutarti a diagnosticare e gestire i conflitti attivi-attivi. La registrazione dei conflitti in questa tabella si verifica solo se l'impostazione è impostata su true. pgactive.log_conflicts_to_table
L'estensione pgactive registra anche i conflitti nel file di registro PostgreSQL quando log_min_messages è impostato su o, indipendentemente dall'impostazione. LOG
lower
pgactive.log_conflicts_to_table
Usa la tabella della cronologia dei conflitti per:
-
Misura la frequenza con cui l'applicazione crea conflitti
-
Identifica dove si verificano i conflitti
-
Migliora la tua applicazione per ridurre i tassi di conflitto
-
Rileva i casi in cui la risoluzione dei conflitti non produce i risultati desiderati
-
Determina dove sono necessari i trigger di conflitto definiti dall'utente o le modifiche alla progettazione delle applicazioni
Per i conflitti di riga, puoi facoltativamente registrare i valori di riga. Questo è controllato dall'pgactive.log_conflicts_to_table
impostazione. Nota:
-
Questa è un'opzione globale a livello di database
-
Non esiste un controllo per tabella sulla registrazione dei valori di riga
-
Non viene applicato alcun limite ai numeri di campo, agli elementi dell'array o alla lunghezza dei campi
-
L'attivazione di questa funzionalità potrebbe non essere consigliabile se si lavora con righe da più megabyte che potrebbero causare conflitti
Poiché la tabella della cronologia dei conflitti contiene i dati di ogni tabella del database (ognuna con schemi potenzialmente diversi), i valori delle righe registrati vengono archiviati come campi JSON. Il file JSON viene creato utilizzandorow_to_json
, in modo simile a chiamarlo direttamente da SQL. PostgreSQL non fornisce json_to_row
una funzione, quindi avrai bisogno di codice specifico per la tabella (PL/pgSQL, PL/Python, PL/Perlin, ecc.) per ricostruire una tupla di tipo composito dal JSON registrato.
Nota
Il supporto per i conflitti definiti dall'utente è pianificato come future funzionalità di estensione.