Prije ili kasnije, mnogi se susreću s potrebom masovnog popravljanja nečega u evidenciji tablice. Već sam reci mi kako to učiniti bolje, a kako - bolje je ne raditi. Danas ću govoriti o drugom aspektu masovnog ažuriranja - o okidačima.
Na primjer, na stolu u kojem trebate nešto popraviti, visi zli okidač ON UPDATE, prenoseći sve promjene na neke agregate. I morate ažurirati sve (inicijalizirati novo polje, na primjer) tako pažljivo da ti agregati ne budu pogođeni.
Samo isključimo okidače!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
UPDATE ...; -- тут долго-долго
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
Zapravo, to je sve - sve visi.
Jer ALTER TABLE nameće Ekskluzivni pristup- brava pod kojom nitko ne trči paralelno, čak ni jednostavan SELECT, neće moći pročitati ništa iz tablice. Odnosno, dok ova transakcija ne završi, čekat će svi koji žele čak i "samo čitati". I mi to pamtimo UPDATE imamo dugo ...
Brzo ugasimo, pa brzo upalimo!
BEGIN;
ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;
UPDATE ...;
BEGIN;
ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;
Ovdje je situacija već bolja, vrijeme čekanja je puno manje. Ali samo dva problema kvare svu ljepotu:
ALTER TABLE sam čeka sve druge operacije na stolu, uključujući i duge SELECT
Dok je okidač isključen, "proleti" svaka promjena u tablici, čak ni naše. I neće ući u agregate, iako bi trebalo. nevolje!
Upravljanje varijablama sesije
Dakle, u prethodnoj verziji smo naletjeli na temeljnu točku - moramo nekako naučiti okidač da razlikuje "naše" promjene u tablici od "ne naših". “Naši” se preskaču kakvi jesu, ali na “ne naši” se aktiviraju. Za ovo možete koristiti varijable sesije.
Na mehanizam okidača također utječe konfiguracijska varijabla uloga_replikacije_sesije. Omogućeno bez dodatnih uputa (zadano), okidači će se aktivirati kada je uloga replikacije "podrijetlo" (zadano) ili "lokalno". Okidači omogućeni određivanjem ENABLE REPLICA, radit će samo ako način trenutne sesije - "replika", a okidači omogućeni određivanjem ENABLE ALWAYS, radit će bez obzira na trenutni način replikacije.
Posebno ću naglasiti da se postavka ne odnosi na sve-sve odjednom, kao ALTER TABLE, ali samo na našu posebnu posebnu vezu. Ukupno, tako da nijedan okidač aplikacije ne radi:
SET session_replication_role = replica; -- выключили триггеры
UPDATE ...;
SET session_replication_role = DEFAULT; -- вернули в исходное состояние
Stanje unutar okidača
Ali gornja opcija radi za sve okidače odjednom (ili morate unaprijed "izmijeniti" okidače koje ne želite onemogućiti). I ako nam treba "isključiti" jedan određeni okidač?
Nazivi parametara proširenja pišu se na sljedeći način: naziv proširenja nakon kojeg slijedi točka, a zatim sam naziv parametra, slično punim nazivima objekata u SQL-u. Na primjer: plpgsql.variable_conflict.
Budući da se opcije izvan sustava mogu postaviti u procesima koji ne učitavaju odgovarajući modul proširenja, PostgreSQL prihvaća vrijednosti za sva imena s dvije komponente.
Prvo finaliziramo okidač, otprilike ovako:
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;
...
Usput, to se može učiniti "za profit", bez blokiranja, putem CREATE OR REPLACE za funkciju okidača. I onda u posebnoj vezi zakucamo "našu" varijablu:
SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- вернули в исходное состояние