Antipatterns 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 = ''; -- вернули в исходное состояние

Оё шумо роҳҳои дигарро медонед? Дар шарҳҳо мубодила кунед.

Манбаъ: will.com

Илова Эзоҳ