PostgreSQL-i antimustrid: muutke andmeid päästikust mööda minnes

Varem või hiljem seisavad paljud inimesed silmitsi vajadusega midagi tabelikirjetes massiliselt parandada. Mul on juba ütle mulle, kuidas seda paremini teha, ja kuidas – parem on seda mitte teha. Täna räägin massuuenduse teisest aspektist - päästikute kohta.

Näiteks laual, kus peate midagi parandama, on kuri päästik ON UPDATE, kandes kõik muudatused üle mõnele koondnäitajale. Ja kõike tuleb värskendada (näiteks uus väli lähtestada) nii hoolikalt, et need üksused ei muutuks.

Keelame lihtsalt päästikud!

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

Tegelikult on see kõik - kõik ripub.

Sest ALTER TABLE kehtestab Eksklusiivne juurdepääs- lukk, mille all keegi paralleelselt ei jookse, isegi lihtne SELECT, ei saa tabelist midagi välja lugeda. See tähendab, et kuni selle tehingu lõpuleviimiseni ootavad kõik, kes soovivad "lihtsalt lugeda". Ja me mäletame seda UPDATE meil on pikk...

Lülitame selle kiiresti välja ja siis kiiresti sisse!

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

UPDATE ...;

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

Siin on olukord juba parem, ooteaeg on palju väiksem. Kuid ainult kaks probleemi rikuvad kogu ilu:

  • ALTER TABLE ise ootab kõiki muid laual tehtavaid toiminguid, ka pikki SELECT
  • Kui päästik on välja lülitatud "mööda lennata" mis tahes muudatusest tabelis, isegi mitte meie oma. Ja see ei satu agregaatidesse, kuigi peaks. Häda!

Seansi muutujate haldamine

Niisiis, eelmises versioonis puutusime kokku põhimõttelise punktiga - peame kuidagi õpetama päästikut eristama tabelis "meie" muudatusi "mitte meie" muudatustest. "Meie omad" jäetakse praegu vahele, kuid "mitte meie" puhul käivitatakse need. Selleks saate kasutada seansi muutujad.

seansi_replication_roll

Loe manuaal:

Käivitusmehhanismi mõjutab ka konfiguratsioonimuutuja seansi_replication_roll. Kui see on lubatud ilma täiendavate juhisteta (vaikimisi), käivituvad päästikud, kui replikatsiooniroll on „origin” (vaikeseade) või „kohalik”. Päästikud lubatud määramisega ENABLE REPLICA, töötab ainult siis, kui praegune seansi režiim - "replica" ja päästikud on lubatud määramisega ENABLE ALWAYS, töötab olenemata praegusest replikatsioonirežiimist.

Rõhutan eriti, et säte ei kehti kõigile-kõik korraga, as ALTER TABLE, kuid ainult meie eraldiseisvale eriühendusele. Kokku, nii et ükski rakenduse käivitaja ei töötaks:

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

Seisukord päästiku sees

Kuid ülaltoodud valik töötab kõigi päästikute puhul korraga (või peate eelnevalt muutma käivitajaid, mida te ei soovi keelata). Ja kui meil on vaja "välja lülitada" üks konkreetne päästik?

See aitab meid "kasutaja" seansi muutuja:

Laienduse parameetrite nimed kirjutatakse järgmiselt: laienduse nimi, punkt ja seejärel parameetri nimi ise, sarnaselt SQL-i täiskvalifitseeritud objektinimedega. Näiteks: plpgsql.muutuja_konflikt.
Kuna süsteemiväliseid suvandeid saab määrata protsessides, mis vastavat laiendusmoodulit ei laadi, nõustub PostgreSQL kahe komponendiga nimede väärtused.

Esiteks viimistleme päästiku, umbes nii:

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

Muide, seda saab teha "kasumi eesmärgil", ilma blokeerimata, läbi CREATE OR REPLACE päästikufunktsiooni jaoks. Ja siis eraldame spetsiaalses ühenduses "oma" muutuja:


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

Kas teate muid viise? Jagage kommentaarides.

Allikas: www.habr.com

Lisa kommentaar