ПостгреСКЛ антиобрасци: промените податке заобилазећи окидач

Пре или касније, многи људи се суочавају са потребом да нешто масовно исправе у записима табеле. Ја већ имам рекао ми како да то боље урадим, и како - боље је не радити. Данас ћу говорити о другом аспекту масовног ажурирања - о окидачима.

На пример, на табели у којој треба нешто да исправите, налази се зао окидач 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; -- вернули в исходное состояние

Стање унутар окидача

Али горња опција ради за све окидаче одједном (или морате унапред да „измените“ окидаче које не желите да онемогућите). А ако нам затреба "искључи" један одређени окидач?

Ово ће нам помоћи „корисничка“ променљива сесије:

Имена параметара екстензије се пишу на следећи начин: име екстензије, тачка, а затим и само име параметра, слично потпуно квалификованим именима објеката у СКЛ-у. На пример: плпгскл.вариабле_цонфлицт.
Пошто се несистемске опције могу подесити у процесима који не учитавају одговарајући модул проширења, ПостгреСКЛ прихвата вредности за било која имена са две компоненте.

Прво модификујемо окидач, отприлике овако:

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

Да ли знате друге начине? Поделите у коментарима.

Извор: ввв.хабр.цом

Додај коментар