PostgreSQL Antipatterns: muudame andmeid lÀbi triggeeritud

Varsti vĂ”i hiljem seisavad paljud silmitsi vajadusega teha massilisi muudatusi tabeli sissekannetes. Ma olen juba rÀÀkinud, kuidas seda paremini teha, ja kuidas — parem mitte teha. TĂ€na rÀÀgin teise aspekti kohta massilisest uuendamisest — triggertest.

NÀiteks, tabelil, kus peate midagi parandama, on kurjakuulutav trigger ON UPDATE, mis viib kÔik muudatused mingitesse agregaatidesse. Ja teil on vaja kÔik uuendada (uue vÀ field initsialiseerida), nii ettevaatlikult, et need agregaadid ei puutuks.

LĂŒlitame lihtsalt triggerid vĂ€lja!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- siin kaua-kaua
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

PĂ”himĂ”tteliselt, siin ongi kĂ”ik — kĂ”ik on juba kinni.

Sest ALTER TABLE kehtestab AccessExclusive-lukustuse, mille all keegi, kes paralleelselt teostab, isegi lihtne SELECT, ei suuda tabelist midagi lugeda. See tÀhendab, et seni, kuni see tehing ei lÔpe, ootavad kÔik soovijad isegi "lihtsalt lugeda". Ja me mÀletame, et UPDATE meil on pööööörd.

LĂŒlitame siis kiiresti vĂ€lja, seejĂ€rel kiiresti sisse!

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

UPDATE ...;

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

Siin on olukord juba parem, ooteaeg on oluliselt lĂŒhem. Kuid kaks probleemi rikuvad kogu ilu:

  • ALTER TABLE ise ootab kĂ”iki teisi toiminguid tabelis, sealhulgas pikki SELECT
  • Kuni trigger on vĂ€lja lĂŒlitatud, "halveneb" iga muudatus tabelis, isegi mitte meie oma. Ja agregaatidesse see kuidagi ei satu, kuigi peaks. HĂ€da!

Sessioonimuutujate haldamine

Nii et eelmise variandi puhul sattusime pĂ”himĂ”ttelisele punktile — peame kuidagi Ă”petama triggerit eristama "meie" muudatused tabelis "mitte meie" omadest. "Meie" peate kĂŒljele jĂ€tma, kuid "mitte meie" puhul peab see toimima. Selleks vĂ”ime kasutada sessioonimuutujat.

session_replication_role

Lugesime administraatori:

Triggerite kĂ€ivitamise mehanismile mĂ”jub ka konfiguratsioonimuutuja session_replication_role. Ilma tĂ€iendavate juhisteta (vaikimisi) aktiveeritud triggerid toimivad, kui replikatsioonireĆŸiim on — "origin" (vaikimisi) vĂ”i "local". Triggerid, mis aktiveeritakse mÀÀramisega ENABLE REPLICA, toimivad ainult siis, kui aktuaalne seansireĆŸiim — "replica", ja triggerid, mis aktiveeritakse mÀÀramisega ENABLE ALWAYS, toimivad olenemata aktuaalsest replikatsioonireĆŸiimist.

Eriti rĂ”hutan, et seade ei kehti kĂ”igi jaoks korraga, nagu ALTER TABLE, vaid meie eraldi spetsiaalset ĂŒhendust. KokkuvĂ”tteks, et mingeid rakenduse triggereid ei aktiveeruks:

SET session_replication_role = replica; -- vĂ€lja lĂŒlitatud triggerid
UPDATE ...;
SET session_replication_role = DEFAULT; -- tagastatud algsesse olekusse

Tingimus triggeri sees

Kuid ĂŒlaltoodud variant töötab kĂ”igi triggerite puhul korraga (vĂ”i tuleb eelnevalt "muuta" need triggerid, mida ei soovita vĂ€lja lĂŒlitada). Ja kui me peame "vĂ€lja lĂŒlitama" ĂŒhe konkreetse triggeri?

Sellega aitab meid "kasutaja" sessioonimuutuja:

Laiendite parameetrite nimed kirjutatakse jÀrgmiselt: laiendi nimi, punkt ja seejÀrel parameetri nimi, sarnaselt objektide tÀielikele nimedele SQL-is. NÀiteks: plpgsql.variable_conflict.
Kuna mitte-sĂŒsteemsed parameetrid vĂ”ivad olla seatud protsessides, mis ei lae vastavat laiendimoodulit, aktsepteerib PostgreSQL vÀÀrtused mis tahes kahe komponendiga nimede jaoks.

Esiteks viime triggeri töötluse lÀbi, umbes nii:

BEGIN
    -- konverteerimisprotsessis vÔib teha kÔike
    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;
...

Muide, seda saab teha "realses ajas", ilma lukustusteta, lĂ€bi CREATE OR REPLACE -iga triggeri funktsiooni. Ja siis seadistame eraldi ĂŒhenduses "oma" muutuja:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- tagastatud algsesse olekusse

Kas tead muid viise? Jaga oma mÔtteid kommentaarides.

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster