PostgreSQL Antipatterns: aldatu datuak abiarazle bat saihestuz

Lehenago edo beranduago, mahaiko erregistroetan zerbait masiboki konpondu beharraren aurrean aurkitzen dira asko. Dagoeneko daukat esaidazu nola egin hobeto, eta nola - hobe da ez egitea. Gaur eguneraketa masiboaren bigarren alderdiari buruz hitz egingo dut - eragileei buruz.

Adibidez, zerbait konpondu behar duzun mahai batean, abiarazle gaizto bat zintzilikatzen da ON UPDATE, aldaketa guztiak agregatu batzuetara transferituz. Eta dena eguneratu behar duzu (eremu berri bat hasieratu, adibidez) kontu handiz, agregatu horiek eraginik izan ez dezaten.

Desgaitu ditzagun abiarazleak!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- Ρ‚ΡƒΡ‚ Π΄ΠΎΠ»Π³ΠΎ-Π΄ΠΎΠ»Π³ΠΎ
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Egia esan, hori da dena - dena zintzilik dago.

Honegatik ALTER TABLE inposatzen du Sarbide esklusiboa- inor paraleloan exekutatzen ez den sarraila, nahiz eta sinple bat SELECT, ezingo du mahaitik ezer irakurri. Hau da, transakzio hau amaitzen den arte, "irakurtzea besterik ez" nahi duten guztiek itxarongo dute. Eta hori gogoratzen dugu UPDATE luzea dugu...

Desaktibatu dezagun azkar, gero azkar piztu!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
COMMIT;

UPDATE ...;

BEGIN;
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Hemen egoera hobea da jada, itxaron denbora askoz txikiagoa da. Baina bi arazok bakarrik hondatzen dute edertasun guztia:

  • ALTER TABLE bera mahai gainean dauden beste eragiketa guztien zain dago, luzeak barne SELECT
  • Aktibagailua itzalita dagoen bitartean "hegan egin" edozein aldaketa mahaian, ezta gurea ere. Eta ez da agregatuetan sartuko, beharko lukeen arren. Arazoak!

Saioaren aldagaiak kudeatzea

Beraz, aurreko bertsioan, oinarrizko puntu batekin topo egin genuen: nolabait abiarazleari irakatsi behar diogu taulako "gure" aldaketak "ez gureak" bereizten. "Gureak" dagoen bezala saltatzen dira, baina "ez gurean" abiarazten dira. Horretarako erabil dezakezu saioko aldagaiak.

saioa_erreplikatzeko_rola

irakurri eskuzkoa:

Abiarazte-mekanismoa konfigurazio aldagaiak ere eragiten du saioa_erreplikatzeko_rola. Argibide gehigarririk gabe gaituta (lehenetsia), abiarazleak abiaraziko dira erreplikazio-rola "jatorria" (lehenetsia) edo "lokala" denean. Abiarazleak zehaztuz gaituta ENABLE REPLICA, bada bakarrik funtzionatuko du uneko saio modua - "erreplika", eta abiarazleak gaituta zehaztuz ENABLE ALWAYS, uneko erreplikazio modua edozein dela ere funtzionatuko du.

Bereziki azpimarratuko dut ezarpena ez dela guztiak aldi berean aplikatzen, bezala ALTER TABLE, baina gure aparteko konexio berezira bakarrik. Guztira, aplikaziorik ez dezan lanik abiarazteko:

SET session_replication_role = replica; -- Π²Ρ‹ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΠΈ Ρ‚Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹
UPDATE ...;
SET session_replication_role = DEFAULT; -- Π²Π΅Ρ€Π½ΡƒΠ»ΠΈ Π² исходноС состояниС

Aktibatzaile barruko egoera

Baina goiko aukerak abiarazle guztietarako funtzionatzen du aldi berean (edo desgaitu nahi ez dituzun abiarazleak "ordezkatu" behar dituzu aldez aurretik). Eta behar badugu "itzali" abiarazle zehatz bat?

Horrek lagunduko digu "erabiltzailea" saio aldagaia:

Luzapen-parametroen izenak honela idazten dira: luzapenaren izena eta ondoren puntu bat eta gero parametroaren izena bera, SQL-ko objektu-izen osoen antzera. Adibidez: plpgsql.variable_conflict.
Luzapen-modulu egokia kargatzen ez duten prozesuetan sistemaz kanpoko aukerak ezar daitezkeenez, PostgreSQL-k onartzen du bi osagai dituen edozein izenetarako balioak.

Lehenik eta behin, abiarazlea amaitzen dugu, honelako zerbait:

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;
...

Bide batez, hori "irabaziarekin" egin daiteke, blokeatu gabe, bidez CREATE OR REPLACE trigger funtziorako. Eta gero konexio berezian "gure" aldagaia jartzen dugu:


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- Π²Π΅Ρ€Π½ΡƒΠ»ΠΈ Π² исходноС состояниС

Badakizu beste modu batzuk? Partekatu iruzkinetan.

Iturria: www.habr.com

Gehitu iruzkin berria