PostgreSQL antiuzorci: promijenite podatke zaobilazeći okidač

Prije ili kasnije, mnogi se susreću s potrebom da se nešto masovno popravi u tabličnim zapisima. Već jesam reci mi kako da to bolje uradim, 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 zao okidač ON UPDATE, prenoseći sve promjene na neke agregate. I treba da ažurirate sve (na primjer, inicijalizirate novo polje) tako pažljivo da to ne utiče na ove agregate.

Hajde da samo onemoguć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 Pristup ekskluzivno- brava ispod koje niko ne trči paralelno, čak ni obična SELECT, neće moći pročitati ništa sa tabele. Odnosno, dok se ova transakcija ne završi, svi koji žele čak i „samo da čitaju“ čekaće. I sećamo se toga UPDATE imamo dugo...

Brzo ga 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 znatno manje. Ali samo dva problema kvare svu ljepotu:

  • ALTER TABLE sama čeka na sve ostale operacije na stolu, uključujući i duge SELECT
  • Dok je okidač isključen "proleti" bilo koju promjenu u tabeli, čak ni naš. I neće ući u agregate, iako bi trebalo. Nevolja!

Upravljanje varijablama sesije

Dakle, u prethodnoj verziji naišli smo na fundamentalnu stvar - moramo nekako naučiti okidač da razlikuje „naše“ promjene u tabeli od „ne naših“. “Naši” se preskaču kao što jesu, ali na “ne naš” se aktiviraju. Za ovo možete koristiti varijable sesije.

session_replication_role

Čitaj priručnik:

Na mehanizam okidača također utiče konfiguracijska varijabla session_replication_role. Omogućeno bez dodatnih instrukcija (podrazumevano), okidači će se aktivirati kada je uloga replikacije "origin" (podrazumevano) ili "local". Okidači su omogućeni navođenjem ENABLE REPLICA, radiće samo ako režim trenutne sesije - "replika", i okidači omogućeni navođenjem 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 "alternirati" okidače koje ne želite onemogućiti). I ako nam zatreba "isključi" jedan određeni okidač?

Ovo će nam pomoći "korisnička" varijabla sesije:

Imena parametara ekstenzije pišu se na sljedeći način: ime ekstenzije praćeno točkom, a zatim samo ime parametra, slično punim imenima objekata u SQL-u. Na primjer: plpgsql.varijable_conflict.
Budući da se opcije izvan sistema mogu postaviti u procesima koji ne učitavaju odgovarajući modul proširenja, PostgreSQL prihvata vrijednosti za bilo koja imena sa 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, kroz CREATE OR REPLACE za funkciju okidača. A onda u posebnoj vezi ubacujemo "našu" varijablu:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- вернули в исходное состояние

Znate li druge načine? Podijelite u komentarima.

izvor: www.habr.com

Dodajte komentar