PostgreSQL рдЕрдБрдЯреАрдкреЕрдЯрд░реНрди: рдЯреНрд░рд┐рдЧрд░ рдмрд╛рдпрдкрд╛рд╕ рдХрд░реВрди рдбреЗрдЯрд╛ рдмрджрд▓рд╛

рд▓рд╡рдХрд░рдЪ рдХрд┐рдВрд╡рд╛ рдирдВрддрд░, рдкреБрд╖реНрдХрд│рд╛рдВрдирд╛ рдЯреЗрдмрд▓ рд░реЗрдХреЙрд░реНрдбрдордзреНрдпреЗ рдореЛрдареНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд рдХрд╛рд╣реАрддрд░реА рдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рднрд╛рд╕рддреЗ. рдорд╛рдЭреНрдпрд╛рдХрдбреЗ рдЖрдзреАрдЪ рдЖрд╣реЗ рддреЗ рдЪрд╛рдВрдЧрд▓реЗ рдХрд╕реЗ рдХрд░рд╛рдпрдЪреЗ рддреЗ рдорд▓рд╛ рд╕рд╛рдВрдЧрд╛, рдЖрдгрд┐ рдХрд╕реЗ - рддреЗ рди рдХрд░рдгреЗ рдЪрд╛рдВрдЧрд▓реЗ рдЖрд╣реЗ. рдЖрдЬ рдореА рдорд╛рд╕ рдЕрдкрдбреЗрдЯрдЪреНрдпрд╛ рджреБрд╕рд▒реНрдпрд╛ рдкреИрд▓реВрдмрджреНрджрд▓ рдмреЛрд▓рдгрд╛рд░ рдЖрд╣реЗ - рдЯреНрд░рд┐рдЧрд░ рдмрджреНрджрд▓.

рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдПрдЦрд╛рджреНрдпрд╛ рдЯреЗрдмрд▓рд╡рд░ рдЬреНрдпрд╛рдордзреНрдпреЗ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдХрд╛рд╣реАрддрд░реА рдирд┐рд░рд╛рдХрд░рдг рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ, рдПрдХ рд╡рд╛рдИрдЯ рдЯреНрд░рд┐рдЧрд░ рд▓рдЯрдХрддреЛ ON UPDATE, рд╕рд░реНрд╡ рдмрджрд▓ рдХрд╛рд╣реА рд╕рдореБрдЪреНрдЪрдпрд╛рдВрдордзреНрдпреЗ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░рдд рдЖрд╣реЗ. рдЖрдгрд┐ рддреБрдореНрд╣рд╛рд▓рд╛ рд╕рд░реНрд╡рдХрд╛рд╣реА рдЕрджреНрдпрдпрд╛рд╡рдд рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдирд╡реАрди рдлреАрд▓реНрдб рд╕реБрд░реВ рдХрд░рд╛) рдЬреЗрдгреЗрдХрд░реВрди рдпрд╛ рд╕рдореБрдЪреНрдЪрдпрд╛рдВрд╡рд░ рдкрд░рд┐рдгрд╛рдо рд╣реЛрдгрд╛рд░ рдирд╛рд╣реА.

рдЪрд▓рд╛ рдлрдХреНрдд рдЯреНрд░рд┐рдЧрд░ рдЕрдХреНрд╖рдо рдХрд░реВрдпрд╛!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- ╤В╤Г╤В ╨┤╨╛╨╗╨│╨╛-╨┤╨╛╨╗╨│╨╛
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

рдЦрд░рдВ рддрд░, рд╣реЗ рд╕рд░реНрд╡ рдЖрд╣реЗ - рд╕рд░реНрд╡ рдХрд╛рд╣реА рд▓рдЯрдХрдд рдЖрд╣реЗ.

рдХрд╛рд░рдг ALTER TABLE рд▓рд╛рджрддреЛ рдЕрдирдиреНрдп рдкреНрд░рд╡реЗрд╢- рдПрдХ рд▓реЙрдХ рдЬреНрдпрд╛рдЪреНрдпрд╛ рдЦрд╛рд▓реА рдХреЛрдгреАрд╣реА рд╕рдорд╛рдВрддрд░ рдЪрд╛рд▓рдд рдирд╛рд╣реА, рдЕрдЧрджреА рд╕рд╛рдзреЗ рджреЗрдЦреАрд▓ SELECT, рдЯреЗрдмрд▓рдордзреВрди рдХрд╛рд╣реАрд╣реА рд╡рд╛рдЪрдгреНрдпрд╛рд╕ рд╕рдХреНрд╖рдо рд╣реЛрдгрд╛рд░ рдирд╛рд╣реА. рдореНрд╣рдгрдЬреЗрдЪ, рд╣рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рдВрдкреЗрдкрд░реНрдпрдВрдд, "рдлрдХреНрдд рд╡рд╛рдЪреВ" рдЗрдЪреНрдЫрд┐рдд рдЕрд╕рд▓реЗрд▓реЗ рдкреНрд░рддреНрдпреЗрдХрдЬрдг рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрд▓. рдЖрдгрд┐ рдЖрдореНрд╣реА рддреЗ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рддреЛ UPDATE рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдПрдХ рд▓рд╛рдВрдм рдЖрд╣реЗ ...

рдЪрд▓рд╛ рддреЗ рддреНрд╡рд░реАрдд рдмрдВрдж рдХрд░реВрдпрд╛, рдирдВрддрд░ рддреЗ рдкрдЯрдХрди рдЪрд╛рд▓реВ рдХрд░реВрдпрд╛!

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

UPDATE ...;

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

рдпреЗрдереЗ рдкрд░рд┐рд╕реНрдерд┐рддреА рдЖрдзреАрдЪ рдЪрд╛рдВрдЧрд▓реА рдЖрд╣реЗ, рдкреНрд░рддреАрдХреНрд╖рд╛ рд╡реЗрд│ рдЦреВрдкрдЪ рдХрдореА рдЖрд╣реЗ. рдкрд░рдВрддреБ рдХреЗрд╡рд│ рджреЛрди рд╕рдорд╕реНрдпрд╛ рд╕рд░реНрд╡ рд╕реМрдВрджрд░реНрдп рдЦрд░рд╛рдм рдХрд░рддрд╛рдд:

  • ALTER TABLE рд╕реНрд╡рддрдГ рдЯреЗрдмрд▓рд╡рд░реАрд▓ рдЗрддрд░ рд╕рд░реНрд╡ рдСрдкрд░реЗрд╢рдиреНрд╕рдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рдд рдЖрд╣реЗ, рдЬреНрдпрд╛рдд рд▓рд╛рдВрдмрд▓рдЪрдХ рдЧреЛрд╖реНрдЯреАрдВрдЪрд╛ рд╕рдорд╛рд╡реЗрд╢ рдЖрд╣реЗ SELECT
  • рдЯреНрд░рд┐рдЧрд░ рдмрдВрдж рдЕрд╕рддрд╛рдирд╛ рдХреЛрдгрддрд╛рд╣реА рдмрджрд▓ "рдлреНрд▓рд╛рдп рдмрд╛рдп" рдЯреЗрдмрд▓рдордзреНрдпреЗ, рдЖрдордЪреЗрд╣реА рдирд╛рд╣реА. рдЖрдгрд┐ рддреЗ рдПрдХрддреНрд░реАрдд рдпреЗрдгрд╛рд░ рдирд╛рд╣реА, рдЬрд░реА рддреЗ рдЕрд╕рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ. рддреНрд░рд╛рд╕!

рд╕рддреНрд░ рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓реНрд╕ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ

рддрд░, рдорд╛рдЧреАрд▓ рдЖрд╡реГрддреНрддреАрдд, рдЖрдореНрд╣реА рдПрдХрд╛ рдореВрд▓рднреВрдд рдореБрджреНрджреНрдпрд╛рд╡рд░ рдЕрдбрдЦрд│рд▓реЛ - рдЖрдореНрд╣рд╛рд▓рд╛ "рдЖрдордЪреЗ рдирд╛рд╣реА" рдкрд╛рд╕реВрди рдЯреЗрдмрд▓рдордзреАрд▓ "рдЖрдордЪреЗ" рдмрджрд▓ рд╡реЗрдЧрд│реЗ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЯреНрд░рд┐рдЧрд░рд▓рд╛ рдХрд╕реЗ рддрд░реА рд╢рд┐рдХрд╡рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓. "рдЖрдордЪреЗ" рдЬрд╕реЗ рдЖрд╣реЗ рддрд╕реЗ рд╡рдЧрд│рд▓реЗ рдЖрд╣реЗ, рдкрд░рдВрддреБ "рдЖрдордЪреЗ рдирд╛рд╣реА" рд╡рд░ рддреЗ рдЯреНрд░рд┐рдЧрд░ рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд. рдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣реА рд╡рд╛рдкрд░реВ рд╢рдХрддрд╛ рд╕рддреНрд░ рдЪрд▓.

рд╕рддреНрд░_рдкреНрд░рддрд┐рдХреГрддреА_рднреВрдорд┐рдХрд╛

рд╡рд╛рдЪрд╛ рдореЕрдиреНрдпреБрдЕрд▓:

рдЯреНрд░рд┐рдЧрд░ рдпрдВрддреНрд░рдгрд╛ рджреЗрдЦреАрд▓ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓рджреНрд╡рд╛рд░реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрддреЗ рд╕рддреНрд░_рдкреНрд░рддрд┐рдХреГрддреА_рднреВрдорд┐рдХрд╛. рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реВрдЪрдирд╛рдВрд╢рд┐рд╡рд╛рдп (рдбреАрдлреЙрд▓реНрдЯ) рд╕рдХреНрд╖рдо рдХреЗрд▓реЗрд▓реЗ, рдЬреЗрд╡реНрд╣рд╛ рдкреНрд░рддрд┐рдХреГрддреА рднреВрдорд┐рдХрд╛ "рдореВрд│" (рдбреАрдлреЙрд▓реНрдЯ) рдХрд┐рдВрд╡рд╛ "рд╕реНрдерд╛рдирд┐рдХ" рдЕрд╕реЗрд▓ рддреЗрд╡реНрд╣рд╛ рдЯреНрд░рд┐рдЧрд░ рд╕рдХреНрд░рд┐рдп рд╣реЛрддреАрд▓. рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реВрди рдЯреНрд░рд┐рдЧрд░ рд╕рдХреНрд╖рдо рдХреЗрд▓реЗ ENABLE REPLICA, рддрд░рдЪ рдХрд╛рд░реНрдп рдХрд░реЗрд▓ рд╡рд░реНрддрдорд╛рди рд╕рддреНрд░ рдореЛрдб - "рдкреНрд░рддрд┐рдХреГрддреА", рдЖрдгрд┐ рдЯреНрд░рд┐рдЧрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реВрди рд╕рдХреНрд╖рдо рдХреЗрд▓реЗ ENABLE ALWAYS, рд╡рд░реНрддрдорд╛рди рдкреНрд░рддрд┐рдХреГрддреА рдореЛрдбрдХрдбреЗ рджреБрд░реНрд▓рдХреНрд╖ рдХрд░реВрди рдХрд╛рд░реНрдп рдХрд░реЗрд▓.

рдореА рд╡рд┐рд╢реЗрд╖рддрдГ рдпрд╛рд╡рд░ рдЬреЛрд░ рджреЗрдИрди рдХреА рд╕реЗрдЯрд┐рдВрдЧ рдПрдХрд╛рдЪ рд╡реЗрд│реА рд╕рд░реНрд╡рд╛рдВрд╡рд░ рд▓рд╛рдЧреВ рд╣реЛрдд рдирд╛рд╣реА, рдЬрд╕реЗ ALTER TABLE, рдкрд░рдВрддреБ рдХреЗрд╡рд│ рдЖрдордЪреНрдпрд╛ рд╕реНрд╡рддрдВрддреНрд░ рд╡рд┐рд╢реЗрд╖ рдХрдиреЗрдХреНрд╢рдирд╕рд╛рдареА. рдПрдХреВрдг, рдЬреЗрдгреЗрдХрд░реБрди рдХреЛрдгрддрд╛рд╣реА рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛рд░реНрдп рдЯреНрд░рд┐рдЧрд░ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА:

SET session_replication_role = replica; -- ╨▓╤Л╨║╨╗╤О╤З╨╕╨╗╨╕ ╤В╤А╨╕╨│╨│╨╡╤А╤Л
UPDATE ...;
SET session_replication_role = DEFAULT; -- ╨▓╨╡╤А╨╜╤Г╨╗╨╕ ╨▓ ╨╕╤Б╤Е╨╛╨┤╨╜╨╛╨╡ ╤Б╨╛╤Б╤В╨╛╤П╨╜╨╕╨╡

рдЯреНрд░рд┐рдЧрд░рдЪреНрдпрд╛ рдЖрдд рд╕реНрдерд┐рддреА

рдкрд░рдВрддреБ рд╡рд░реАрд▓ рдкрд░реНрдпрд╛рдп рдПрдХрд╛рдЪ рд╡реЗрд│реА рд╕рд░реНрд╡ рдЯреНрд░рд┐рдЧрд░рд╕рд╛рдареА рдХрд╛рд░реНрдп рдХрд░рддреЛ (рдХрд┐рдВрд╡рд╛ рддреБрдореНрд╣рд╛рд▓рд╛ "рдкрд░реНрдпрд╛рдпреА" рдЯреНрд░рд┐рдЧрд░реНрд╕ рдЖрдЧрд╛рдК рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рдЬреЗ рддреБрдореНрд╣реА рдЕрдХреНрд╖рдо рдХрд░реВ рдЗрдЪреНрдЫрд┐рдд рдирд╛рд╣реА). рдЖрдгрд┐ рдЖрдореНрд╣рд╛рд▓рд╛ рдЧрд░рдЬ рдЕрд╕рд▓реНрдпрд╛рд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЯреНрд░рд┐рдЧрд░ "рдмрдВрдж рдХрд░рд╛".?

рд╣реЗ рдЖрдореНрд╣рд╛рд▓рд╛ рдорджрдд рдХрд░реЗрд▓ "рд╡рд╛рдкрд░рдХрд░реНрддрд╛" рд╕рддреНрд░ рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓:

рдПрдХреНрд╕реНрдЯреЗрдВрд╢рди рдкреЕрд░рд╛рдореАрдЯрд░рдЪреА рдирд╛рд╡реЗ рдЦрд╛рд▓реАрд▓рдкреНрд░рдорд╛рдгреЗ рд▓рд┐рд╣рд┐рд▓реА рдЖрд╣реЗрдд: рд╡рд┐рд╕реНрддрд╛рд░рд╛рдЪреЗ рдирд╛рд╡ рдирдВрддрд░ рдбреЙрдЯ рдЖрдгрд┐ рдирдВрддрд░ рдкреЕрд░рд╛рдореАрдЯрд░рдЪреЗ рдирд╛рд╡, SQL рдордзреАрд▓ рд╕рдВрдкреВрд░реНрдг рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╛рд╡рд╛рдВрд╕рд╛рд░рдЦреЗрдЪ. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде: plpgsql.variable_conflict.
рдХрд╛рд░рдг рдЖрдЙрдЯ-рдСрдл-рд╕рд┐рд╕реНрдЯреАрдо рдкрд░реНрдпрд╛рдп рдкреНрд░рдХреНрд░рд┐рдпрд╛рдВрдордзреНрдпреЗ рд╕реЗрдЯ рдХреЗрд▓реЗ рдЬрд╛рдК рд╢рдХрддрд╛рдд рдЬреЗ рдпреЛрдЧреНрдп рд╡рд┐рд╕реНрддрд╛рд░ рдореЙрдбреНрдпреВрд▓ рд▓реЛрдб рдХрд░рдд рдирд╛рд╣реАрдд, PostgreSQL рд╕реНрд╡реАрдХрд╛рд░рддреЗ рджреЛрди рдШрдЯрдХрд╛рдВрд╕рд╣ рдХреЛрдгрддреНрдпрд╛рд╣реА рдирд╛рд╡рд╛рдВрд╕рд╛рдареА рдореВрд▓реНрдпреЗ.

рдкреНрд░рдердо, рдЖрдореНрд╣реА рдЯреНрд░рд┐рдЧрд░ рдЕрдВрддрд┐рдо рдХрд░рддреЛ, рдЕрд╕реЗ рдХрд╛рд╣реАрддрд░реА:

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

рддрд╕реЗ, рд╣реЗ рдмреНрд▓реЙрдХ рди рдХрд░рддрд╛, "рдирдлреНрдпрд╛рд╕рд╛рдареА" рдХреЗрд▓реЗ рдЬрд╛рдК рд╢рдХрддреЗ CREATE OR REPLACE рдЯреНрд░рд┐рдЧрд░ рдлрдВрдХреНрд╢рдирд╕рд╛рдареА. рдЖрдгрд┐ рдордЧ рд╡рд┐рд╢реЗрд╖ рдХрдиреЗрдХреНрд╢рдирдордзреНрдпреЗ рдЖрдореНрд╣реА "рдЖрдордЪреЗ" рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рдХреЙрдХ рдХрд░рддреЛ:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- ╨▓╨╡╤А╨╜╤Г╨╗╨╕ ╨▓ ╨╕╤Б╤Е╨╛╨┤╨╜╨╛╨╡ ╤Б╨╛╤Б╤В╨╛╤П╨╜╨╕╨╡

рддреБрдореНрд╣рд╛рд▓рд╛ рдЗрддрд░ рдорд╛рд░реНрдЧ рдорд╛рд╣рд┐рдд рдЖрд╣реЗрдд рдХрд╛? рдЯрд┐рдкреНрдкрдгреНрдпрд╛рдВрдордзреНрдпреЗ рд╕рд╛рдорд╛рдпрд┐рдХ рдХрд░рд╛.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛