PostgreSQL Antipatterns: changing data bypassing the trigger

Varsti vĂ”i hiljem puutuvad paljud kokku vajadusega midagi massiliselt tabeli kirjetes parandada. Olen juba rÀÀkinud, kuidas seda paremini teha, ja kuidas — mitte teha. TĂ€na rÀÀgin massiivse uuendamise teisest aspektist — kĂ€ivituvatest trigeritest.

NÀiteks, tabelil, kus peate midagi korrigeerima, on kurja triger ON UPDATE, mis viib kÔik muudatused mingitesse aggregeeridesse. Ja teil on vaja kÔik uuendada (uue vÀlja initsialiseerida nÀiteks) nii ettevaatlikult, et need aggregeedid ei puudutaks.

LĂ€hme lihtsalt trigerite vĂ€ljalĂŒlitamise teed!

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

Loomulikult, siin see kĂ”ik on — kĂ”ik on juba kĂ€imas.

Sest ALTER TABLE kehtestab AccessExclusive-lukustuse all, mille all keegi, kes teostab samaaegset tööd, isegi lihtne SELECT, ei saa tabelist midagi lugeda. See tĂ€hendab, et kuni see tehing ei ole lĂ”ppenud, ootavad kĂ”ik, kes tahavad isegi 'lihtsalt lugeda'. Ja me mĂ€letame, et KUUDA meil on pi-ii-ikalt


LĂ€hme siis kiiresti vĂ€lja lĂŒlitama, siis kiiresti sisse lĂŒlitame!

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 ootab endiselt kĂ”iki teisi operatsioone tabelis, sealhulgas pikki SELECT
  • Praegu on triger vĂ€lja lĂŒlitatud, igal muutusel on vĂ”imalus «mööda minna» tabelis, isegi mitte meie oma. Ja agregaatidesse ei pÀÀse, kuigi peaks. HĂ€da!

Seansi muutujate haldamine

Nii et eelmisel variandil sattusime pĂ”himĂ”ttelisele punktile — peame kuidagi Ă”petama triggest eristama tabelis «meie» muudatusi «mitte meie» omadest. «Meie» lubame sellisena, kuid «mitte meie» korral peame reageerima. Selleks saab kasutada seansi muutujaid.

session_replication_role

Lugeda kasutajate kÀsiraamat:

Triggerite aktiveerimise mehhanismile mĂ”jutab ka konfiguratsioonimuutuja session_replication_role. Ilma tĂ€iendavate mĂ€rkusteta (vaikimisi) aktiveeruvad triggerrid, kui replikatsiooni roll on — „origin“ (vaikimisi) vĂ”i „local“. Trigged, mis aktiveeritakse nĂ€idatud ENABLE REPLICA, aktiveeruvad ainult siis, kui praegune seanss on — „replica“, ning trigged, mis aktiveeritakse nĂ€idatud ENABLE ALWAYS, aktiveeruvad olenemata praegusest replikatsiooni reĆŸiimist.

Eriti rĂ”hutan, et seadistus ei kehti kĂ”igile korraga, nagu ALTER TABLE, vaid ainult meie konkreetse spetsiaalsete ĂŒhenduste jaoks. Seega, et ei toimiks mingeid rakenduslikke kĂ€ivitusmehhanisme:

SET session_replication_role = replica; -- keelame kÀivitushoobad
UPDATE ...;
SET session_replication_role = DEFAULT; -- taastame algse seisundi

KĂ€ivitushoobade tingimus

Kuid eespool toodud variant töötab kĂ”igi kĂ€ivitushoobade jaoks korraga (vĂ”i peab eelnevalt "muutma" neid kĂ€ivitushoobasid, mida ei soovi keelata). Aga kui me peame "keelama" ĂŒhe konkreetse kĂ€ivitushoova?

Seda aitab meil "kasutaja" seansi muutuja:

Laiendite parameetrite nimed kirjutatakse jÀrgmiselt: laiendi nimi, punkt ja seejÀrel parameetri enda nimi, sarnaselt SQL-i tÀielike objektinimedega. NÀiteks: plpgsql.variable_conflict.
Kuna sĂŒsteemi vĂ€list parameetrit vĂ”ib seadistada protsessides, mis ei laadita vastavat laiendimoodulit, aktsepteerib PostgreSQL vÀÀrtusi igasuguste kahe komponendiga nimede jaoks.

Alustame kÀivitushoova tÀiustamist 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;
...

Üksikasjalikult, seda saab teha "reaalses" ajas, ilma blokeeringuteta, lĂ€bi CREATE OR REPLACE triggereid funktsioonide jaoks. SeejĂ€rel mÀÀrame spetsiaalses ĂŒhenduses meie muutuja:


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

Kas tead muid viise? Jagage kommentaarides.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster