Varsti vĂ”i hiljem seisavad paljud silmitsi vajadusega teha massilisi muudatusi tabeli sissekannetes. Ma olen juba , 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 TABLEise ootab kĂ”iki teisi toiminguid tabelis, sealhulgas pikkiSELECT- 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 .
session_replication_role
Lugesime :
Triggerite kĂ€ivitamise mehanismile mĂ”jub ka konfiguratsioonimuutuja . 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ÀÀramisegaENABLE 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 olekusseTingimus 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 :
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
