Előbb-utóbb sokan szembesülnek azzal a szükséglettel, hogy valamit tömegesen módosítaniuk kell a táblázatban. Már , és arról is, hogyan nem. Ma a tömeges frissítés második aspektusáról fogok beszélni — a triggerekről.
Például, ha van egy tábla, amelyen valamit módosítani kell, ott lóg egy csúnya trigger ON UPDATE, amely minden változást átvisz valamilyen aggregátumba. Önnek viszont mindent frissítenie kell (például egy új mező inicializálása), annyira óvatosan, hogy ezek az aggregátumok ne érintődjenek.
Csak egyszerűen kapcsoljuk ki a triggereket!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- itt hosszasan
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Igazából itt minden megvan — már minden lóg.
Mert ALTER TABLE rávonatkozik Kizáró hozzáférés-a blokkolás, alatt amely senki párhuzamosan végrehajtva, még egy egyszerű SELECT, semmit nem tud majd olvasni a táblázatból. Tehát amíg ez a tranzakció nem ér véget, mindenki, aki csak „olvashatna”, várakozni fog. És emlékszünk arra, hogy UPDATE nálunk e-él-hosszú…
Akkor gyorsan kapcsoljuk ki, majd gyorsan kapcsoljuk be!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Itt a helyzet már jobb, a várakozási idő lényegesen rövidebb. De két probléma elrontja az egész szépséget:
ALTER TABLEazt várja el az összes többi művelet a táblázaton, beleértve a hosszúakatSELECT- Míg a trigger ki van kapcsolva, minden változás a táblázatban, még csak nem is a miénk, „el fog repülni”. És az aggregátokba hát nem fog bejutni, pedig kellene. Nagy baj!
Sesszióváltozók kezelése
Tehát az előző változaton egy alapvető pontra bukkantunk — valahogy meg kell tanítanunk a triggert megkülönböztetni a „mi” módosításainkat a „nem mi”-től. A „mi”-ket át kell engedni, a „nem mi”-kre pedig reagálni. .
session_replication_role
Olvassuk :
A triggerekről való működésre a konfigurációs változó is hatással van . Alapértelmezetten (további utasítások nélkül) a triggereket aktiválják, amikor a replikációs szerep — „origin” (alapértelmezetten) vagy „local”. A triggereket, amelyeket
ENABLE REPLICA, csak akkor aktiválják, ha a jelenlegi észlelési mód — „replica”, és a triggereket, amelyeketENABLE ALWAYS, minden körülmények között aktiválják, függetlenül a jelenlegi replikációs módtól.
Különösen hangsúlyozom, hogy a beállítás nem mindenkire vonatkozik egyszerre, mint ALTER TABLE, és csak a saját különleges kapcsolódásunkhoz. Összességében, hogy ne működjenek semmilyen alkalmazási trigger:
SET session_replication_role = replica; -- a triggerek letiltva
UPDATE ...;
SET session_replication_role = DEFAULT; -- visszaállítottuk az alapállapototA triggeren belüli feltétel
De a fent említett példa minden triggerre egyszerre működik (vagy előre "alterálnunk" kell a triggert, amit nem szeretnénk letiltani). De ha nekünk szükségünk van arra, hogy "leállítsunk" egy konkrét triggert?
Ebben segít nekünk :
A kiterjesztések paramétereinek nevei a következőképpen íródnak: a kiterjesztés neve, pont, majd a tényleges paraméter neve, hasonlóan az SQL objektumok teljes nevéhez. Például: plpgsql.variable_conflict.
Mivel a nem rendszeres paraméterek a megfelelő kiterjesztési modul betöltése nélkül is beállíthatók a folyamatokban, a PostgreSQL elfogadja értékeket bármilyen kétkomponensű névhez.
Először dolgozzuk ki a triggert, körülbelül így:
BEGIN
-- a konverziós folyamat során mindent lehet csinálni
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;
... Egyébként ezt "élőben" is meg lehet csinálni, zárak nélkül, a következők által CREATE OR REPLACE a trigger funkcióhoz. Aztán a különleges kapcsolaton aktiváljuk a "saját" változónkat:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- visszaállítottuk az alapállapotot
Ismersz más módszereket? Oszd meg a véleményed a megjegyzésekben.
Forrás: habr.com
