Tid eller annet veit mange at dei mĂ„ gjere ei masseoppdatering i tabellar. Eg har allereie , og om korleis det er best Ă„ unngĂ„ det. I dag vil eg ta for meg den andre aspekten ved masseoppdatering â utlĂžsing av triggarar.
For eksempel, i tabellen der du mÄ gjere endringar, heng det ein ondskapsfull trigger ON UPDATE, som flyttar alle endringar til nokre aggregat. Og du mÄ oppdatere alt (for eksempel initialisere eit nytt felt) sÄ forsiktig at desse aggregata ikkje blir pÄverka.
La oss berre slÄ av triggerane!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- her tar det tid
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Eigentleg er det alt â alt heng i.
Fordi ALTER TABLE det pÄleggjer AccessExclusive-lÄsing, som gjer at ingen som stÄr parallel med spÞrsmÄlet, til og med ein enkel SELECT, kan lese noko frÄ tabellen. Dette betyr at sÄ lenge denne transaksjonen ikkje er avslutta, vil dei som vil nysgjerrig sjÄ, vere i kÞ. Og vi husker at UPDATE vi har ei laaaaang...
La oss dÄ slÄ av raskt, og sÄ slÄ pÄ igjen raskt!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;Her er situasjonen mykje betre, ventetida er betydelig kortare. Men det er to problem som Ăžydelegg all skjĂžnnhet:
ALTER TABLEden ventar pÄ alle andre operasjonar i tabellen, inkludert langeSELECT- Mens triggeren er slÄtt av, "vil glippe" alle endringar i tabellen, til og med ikkje vÄre. Og dei vil ikkje bli plukka opp i aggregata, sjÞlv om det burde. Forferdeleg!
HÄndtering av sesjonsvariabler
SĂ„, i forrige alternativ mĂžtte vi eit grunnleggjande poeng â vi mĂ„ pĂ„ ein eller anna mĂ„te lĂŠre triggeren Ă„ skille mellom "vĂ„re" endringar i tabellen og "ikkje vĂ„re". La "vĂ„re" gĂ„ som dei er, og reager pĂ„ "ikkje vĂ„re". For dette kan ein bruke .
session_replication_role
Les :
Den mekanismen for utlÞysing av triggarar pÄverkas ogsÄ av den konfigurasjonsvariabelen . Inkludert utan ekstra instruksjonar (standard) vil triggarar bli utlÞyst nÄr replikasjonsrolla er "origin" (standard) eller "local". Triggarar som er inkludert med
ENABLE REPLICA, vil bli utlĂžyst berre dersom den noverande sesjonsmodus er "replica", og triggarar som er inkludert medENABLE ALWAYS, vil bli utlĂžyst uavhengig av den noverande replikasjonsmodusen.
Eg vil spesielt understreke at innstillinga gjelder ikkje alle samtidige, som ALTER TABLE, men kun til vÄr separate spesialforbindelse. SÄ for Ä unngÄ at noen applikasjonstriggere utlÞses:
SET session_replication_role = replica; -- deaktiverte triggerne
UPDATE ...;
SET session_replication_role = DEFAULT; -- tilbake til standardstatusBetingelsen inne i triggeren
Men alternativet ovenfor fungerer for alle triggerne pÄ en gang (eller mÄ vi «endre» pÄ forhÄnd de triggerne vi ikke Þnsker Ä deaktivere). Men hvis vi trenger Ä «deaktivere» én spesifikk trigger?
Dette vil hjelpe oss med :
Navnene pÄ parametrene for utvidelser skrives pÄ fÞlgende mÄte: utvidelsesnavn, punktum og sÄ selve parameterens navn, lik fullstendige objektnavn i SQL. For eksempel: plpgsql.variable_conflict.
Siden ikke-systemparametere kan settes i prosesser som ikke laster den relevante utvidelsesmodulen, godtar PostgreSQL verdier for alle navn med to komponenter.
FĂžrst oppdaterer vi triggeren, omtrent slik:
BEGIN
-- prosessen for konvertering kan gjĂžre alt
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;
... Forresten, dette kan gjÞres «live», uten lÄs, via CREATE OR REPLACE for triggerfunksjonen. Og sÄ i spesialforbindelsen setter vi vÄr egen variabel:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- tilbake til standardstatus
Kjenner du andre metoder? Del i kommentarfeltet.
Kilde: habr.com
