PostgreSQL Antipatterns: рдЯреНрд░рд┐рдЧрд░рд▓рд╛рдИ рдмрд╛рдЗрдкрд╛рд╕ рдЧрд░реЗрд░ рдбрд╛рдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реНрдиреБрд╣реЛрд╕реН

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

рдЙрджрд╛рд╣рд░рдг рдХреЛ рд▓рд╛рдЧреА, рдПрдХ рдЯреЗрдмрд▓ рдорд╛ рдЬрд╕рдорд╛ рддрдкрд╛рдЗрдБ рдХреЗрд╣рд┐ рдареАрдХ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ, рдПрдХ рджреБрд╖реНрдЯ рдЯреНрд░рд┐рдЧрд░ рд╣реНрдпрд╛рдЩреНрдЧ рдЫ 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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди