PostgreSQL Antipatterns: chanje done kontoune yon deklanche

Pi bonè oswa pita, anpil moun ap fè fas ak nesesite pou yo ranje twouve yon bagay nan dosye yo tab. Mwen deja di m kijan pou m fè l pi byen, ak ki jan - li se pi bon pa fè li. Jodi a mwen pral pale sou dezyèm aspè nan aktyalizasyon an mas - sou deklanche.

Pou egzanp, sou yon tab kote ou bezwen ranje yon bagay, yon deklanche sa ki mal pandye ON UPDATE, transfere tout chanjman nan kèk total. Epi ou bezwen mete ajou tout bagay (inisyalize yon nouvo jaden, pou egzanp) ak anpil atansyon ke total sa yo pa afekte.

Ann jis enfim deklanche yo!

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

An reyalite, se tout - tout bagay pandye.

Paske ALTER TABLE enpoze Aksè eksklizif- yon seri anba ki pa gen moun ap kouri nan paralèl, menm yon senp SELECT, p ap kapab li anyen nan tab la. Sa vle di, jiskaske tranzaksyon sa a fini, tout moun ki vle menm "jis li" ap tann. E nou sonje sa UPDATE nou gen yon long...

An nou byen vit fèmen l ', Lè sa a, byen vit vire l'!

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

UPDATE ...;

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

Isit la sitiyasyon an deja pi bon, tan an ap tann se anpil mwens. Men, sèlman de pwoblèm gate tout bote a:

  • ALTER TABLE tèt li ap tann pou tout lòt operasyon sou tab la, ki gen ladan yo ki long SELECT
  • Pandan ke deklanche a koupe "mouch pa" nenpòt chanjman nan tab la, pa menm nou. Epi li pa pral antre nan total yo, byenke li ta dwe. Pwoblèm!

Jere varyab sesyon yo

Se konsa, nan vèsyon anvan an, nou bite sou yon pwen fondamantal - nou bezwen yon jan kanmenm anseye deklanche a fè distenksyon ant chanjman "nou" nan tablo a ak "pa nou". "Nou" yo sote jan yo ye, men sou "pa nou" yo deklanche. Pou sa ou ka itilize varyab sesyon yo.

wòl_replikasyon_sesyon

Li manyèl:

Mekanis deklanche a afekte tou pa varyab konfigirasyon an wòl_replikasyon_sesyon. Aktive san enstriksyon adisyonèl (default), deklanche yo pral dife lè wòl nan replikasyon se "orijin" (default) oswa "lokal". Deklanche pèmèt lè yo espesifye ENABLE REPLICA, ap travay sèlman si mòd sesyon aktyèl la - "replik", ak deklannche pèmèt pa espesifye ENABLE ALWAYS, ap travay kèlkeswa mòd replikasyon aktyèl la.

Mwen pral espesyalman mete aksan sou ke anviwònman an pa aplike nan tout-tout nan yon fwa, kòm ALTER TABLE, men sèlman nan koneksyon espesyal separe nou an. An total, pou pa gen aplikasyon deklanche travay:

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

Kondisyon andedan deklanche

Men, opsyon ki pi wo a ap travay pou tout deklannche nan yon fwa (oswa ou bezwen "altène" deklanche davans ke ou pa vle enfim). E si nou bezwen "fèmen" yon sèl deklanche espesifik?

Sa ap ede nou varyab sesyon "itilizatè".:

Non paramèt ekstansyon yo ekri jan sa a: non ekstansyon an ki te swiv pa yon pwen ak Lè sa a, non paramèt tèt li, menm jan ak non objè konplè nan SQL. Pa egzanp: plpgsql.variable_conflict.
Paske opsyon deyò sistèm yo ka mete nan pwosesis ki pa chaje modil ekstansyon apwopriye a, PostgreSQL aksepte valè pou nenpòt non ki gen de eleman.

Premyèman, nou finalize deklanche a, yon bagay tankou sa a:

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

By wout la, sa a ka fè "pou pwofi", san yo pa bloke, atravè CREATE OR REPLACE pou fonksyon deklanche. Lè sa a, nan koneksyon an espesyal nou chante "nou" varyab:


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

èske w konnen lòt fason? Pataje nan kòmantè yo.

Sous: www.habr.com

Add nouvo kòmantè