Prima o poi, molti si trovano nella necessità di correggere massivamente le registrazioni di una tabella. Ho già , e di come — non farlo affatto. Oggi parlerò del secondo aspetto dell'aggiornamento di massa — l'attivazione dei trigger.
Per esempio, su una tabella, dove devi correggere qualcosa, pende un temuto trigger ON UPDATE, che trasferisce tutte le modifiche in alcuni aggregati. E tu devi aggiornare tutto (inizializzare un nuovo campo, per esempio) in modo tale che questi aggregati non vengano toccati.
Facciamo così, disattiviamo i trigger!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- qui ci vorrà tempo
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;In sostanza, questo è tutto — è già presente.
Perché ALTER TABLE impone AccessExclusive-la blocco, sotto la quale nessuno, nemmeno un'operazione semplice in parallelo, SELECT, potrà leggere nulla dalla tabella. Cioè, finché questa transazione non terminerà, chiunque voglia anche solo «leggere» dovrà aspettare. E noi ricordiamo che UPDATE abbiamo un’operazione molto l-unga…
Allora velocemente disattiviamo, poi velocemente riattiviamo!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Qui la situazione è già migliore, i tempi di attesa sono significativamente più brevi. Ma ci sono due problemi che rovinano tutto:
ALTER TABLEsta aspettando tutte le altre operazioni sulla tabella, comprese le lungheSELECT- Finché il trigger è disattivato, qualsiasi modifica passerà inosservata nella tabella, anche quelle non nostre. E non entrerà negli aggregati, anche se dovrebbe. Un vero peccato!
Gestione delle variabili di sessione
Quindi, nella versione precedente abbiamo affrontato un aspetto fondamentale: dobbiamo in qualche modo insegnare al trigger a distinguere le modifiche "nostre" nella tabella dalle "non nostre". Dobbiamo passare le "nostre" così come sono, mentre per le "non nostre" deve attivarsi. Per questo possiamo utilizzare .
session_replication_role
Leggiamo :
Il meccanismo di attivazione dei trigger è influenzato anche da una variabile di configurazione . I trigger attivati senza ulteriori indicazioni (per impostazione predefinita) si attiveranno quando il ruolo di replica è "origin" (predefinito) o "local". I trigger attivati specificando
ENABLE REPLICA, si attiveranno solo se la modalità corrente della sessione è "replica", e i trigger attivati specificandoENABLE ALWAYS, si attiveranno indipendentemente dalla modalità attuale di replica.
Voglio sottolineare che la configurazione non riguarda tutti immediatamente, ma solo il nostro specifico collegamento speciale. In sintesi, per non attivare nessun trigger applicativo: ALTER TABLESET session_replication_role = replica; -- disattiviamo i trigger UPDATE ...; SET session_replication_role = DEFAULT; -- ripristinato allo stato originale
Condizione all'interno del triggerMa la versione sopra funziona per tutti i trigger contemporaneamente (oppure bisogna "alterare" prima i trigger che non si desidera disattivare). E se abbiamo bisogno di
"disattivare" un singolo trigger specifico "variabile" di sessione personalizzata?
In questo ci aiuterà :
Poiché i parametri non sistemici possono essere impostati nei processi che non caricano il modulo di estensione corrispondente, PostgreSQL accetta
valori per qualsiasi nome con due componenti Prima raffiniamo il trigger, più o meno così:.
BEGIN -- il processo di conversione può fare tutto IF current_setting('mycfg.my_table_convert_process') = 'TRUE' THEN IF TG_OP IN ('INSERT', 'UPDATE') THEN RETURN NEW; ELSE RETURN OLD; END IF; END IF; ...
BEGIN
-- процессу конвертации можно делать все
IF current_setting('mycfg.my_table_convert_process') = 'TRUE' THEN
IF TG_OP IN ('INSERT', 'UPDATE') THEN
RETURN NEW;
ELSE
RETURN OLD;
END IF;
END IF;
... Inoltre, è possibile farlo «in tempo reale», senza bloccaggi, attraverso CREATE OR REPLACE per la funzione trigger. Poi, nel connessione speciale, attiviamo la nostra variabile:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- ripristinato allo stato originale
Conoscete altri metodi? Condividete nei commenti.
Fonte: habr.com
