PostgreSQL Antipatterns: änneren Daten ëmgoen en Ausléiser

Fréier oder spéider si vill konfrontéiert mat der Bedierfnes fir massiv eppes an den Tabelle records ze fixéieren. Ech hu schonn sot mir wéi ech et besser maachen, a wéi - et ass besser net ze maachen. Haut wäert ech iwwer den zweeten Aspekt vum Massupdate schwätzen - iwwer Ausléiser.

Zum Beispill, op engem Dësch, an deem Dir eppes muss fixéieren, hänkt e béisen Ausléiser ON UPDATE, all Ännerungen op e puer Aggregaten iwwerdroen. An Dir musst alles aktualiséieren (en neit Feld initialiséieren, zum Beispill) sou suergfälteg datt dës Aggregaten net beaflosst ginn.

Loosst eis just d'Ausléiser auszeschalten!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- тут долго-долго
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Eigentlech, dat ass alles - alles hänkt schon.

Well ALTER TABLE imposéiert AccessExklusiv- e Spär ënnert deem keen parallel leeft, och eng einfach SELECT, wäert näischt aus dem Dësch liesen kënnen. Dat ass, bis dës Transaktioun eriwwer ass, wäert jidderee dee souguer "just liesen" wëll waarden. A mir erënneren dat UPDATE mir hunn eng laang ...

Loosst eis et séier ausschalten, da schalt et séier un!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;

UPDATE ...;

BEGIN;
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Hei ass d'Situatioun scho besser, d'Waardezäit ass vill manner. Awer nëmmen zwee Probleemer verduerwen all d'Schéinheet:

  • ALTER TABLE selwer waart all aner Operatiounen op den Dësch, dorënner laang SELECT
  • Wärend den Ausléiser aus ass "fléien vun" all Ännerung an der Tabell, och net eis. An et wäert net an d'Aggregate kommen, obwuel et soll. Trouble!

Verwalte Sessiounsvariablen

Also, an der viregter Versioun si mir op e fundamentale Punkt gestouss - mir mussen iergendwéi den Ausléiser léieren fir "eis" Ännerungen an der Tabell vun "net eis" z'ënnerscheeden. "Eis" ginn iwwersprangen wéi et ass, awer op "net eis" gi se ausgeléist. Fir dëst kënnt Dir benotzen Sëtzung Verännerlechen.

session_replication_rolle

Liesen manuell:

Den Ausléisermechanismus gëtt och vun der Konfiguratiounsvariabel beaflosst session_replication_rolle. Aktivéiert ouni zousätzlech Instruktiounen (Standard), Ausléiser brennen wann d'Replikatiounsroll "Origine" (Standard) oder "lokal" ass. Ausléiser aktivéiert duerch Spezifizéierung ENABLE REPLICA, wäert schaffen nëmmen wann aktuell Sëtzung Modus - "Replika", an Ausléiser aktivéiert andeems Dir spezifizéiert ENABLE ALWAYS, funktionnéiert onofhängeg vum aktuelle Replikatiounsmodus.

Ech wäert besonnesch ënnersträichen, datt d'Astellung net all-all op eemol gëllen, wéi ALTER TABLE, awer nëmmen un eis separat speziell Verbindung. Am Ganzen, sou datt keng Applikatioun ausléist Aarbecht:

SET session_replication_role = replica; -- выключили триггеры
UPDATE ...;
SET session_replication_role = DEFAULT; -- вернули в исходное состояние

Zoustand bannent Ausléiser

Awer déi uewe genannte Optioun funktionnéiert fir all Ausléiser gläichzäiteg (oder Dir musst am Viraus "alternéieren" Ausléiser déi Dir net auszeschalten wëllt). A wa mir brauchen "ausschalten" ee spezifeschen Ausléiser?

Dëst wäert eis hëllefen "Benotzer" Sessiounsvariabel:

Extensiounsparameternamen gi wéi follegt geschriwwen: den Extensiounsnumm gefollegt vun engem Punkt an dann de Parameternumm selwer, ähnlech wéi voll Objektnimm an SQL. Zum Beispill: plpgsql.variable_conflict.
Well Out-of-System Optiounen a Prozesser gesat kënne ginn, déi de passenden Extensiounsmodul net lueden, akzeptéiert PostgreSQL Wäerter fir all Nimm mat zwee Komponenten.

Als éischt finaliséieren mir den Ausléiser, eppes wéi dat:

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;
...

Iwwregens, kann dat "fir Gewënn", ouni Spär gemaach ginn, duerch CREATE OR REPLACE fir d'Ausléiserfunktioun. An dann an der spezieller Verbindung hu mir "eis" Variabel:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- вернули в исходное состояние

Kennt Dir aner Weeër? Deelen an de Kommentaren.

Source: will.com

Setzt e Commentaire