Több hónappal ezelőtt az új Microsoft Edge böngésző kiterjesztéseinek száma 162 volt.

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 beszéltem arról, hogyan érdemes ezt csinálni, é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 TABLE azt várja el az összes többi művelet a táblázaton, beleértve a hosszúakat SELECT
  • 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. a sesszióváltozókat.

session_replication_role

Olvassuk kezelői kézikönyv:

A triggerekről való működésre a konfigurációs változó is hatással van session_replication_role. 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, amelyeket ENABLE 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állapotot

A 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 "felhasználói" session változó:

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

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster