Antipatterns PostgreSQL: newid data gan osgoi sbardun

Yn hwyr neu'n hwyrach, mae llawer yn wynebu'r angen i drwsio rhywbeth aruthrol yng nghofnodion y tabl. Rwyf eisoes wedi dywedwch wrthyf sut i'w wneud yn well, a sut - mae'n well peidio â'i wneud. Heddiw byddaf yn siarad am yr ail agwedd ar y diweddariad torfol - am sbardunau.

Er enghraifft, ar fwrdd lle mae angen i chi drwsio rhywbeth, mae sbardun drwg yn hongian ON UPDATE, trosglwyddo pob newid i rai agregau. Ac mae angen i chi ddiweddaru popeth (cychwyn maes newydd, er enghraifft) mor ofalus fel nad yw'r agregau hyn yn cael eu heffeithio.

Gadewch i ni analluogi'r sbardunau!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- тут долго-долго
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

A dweud y gwir, dyna i gyd - mae popeth yn hongian.

Gan fod ALTER TABLE yn gosod Mynediad Unigryw- clo lle nad oes neb yn rhedeg yn gyfochrog, hyd yn oed un syml SELECT, ni fydd yn gallu darllen dim o'r tabl. Hynny yw, nes bod y trafodiad hwn yn dod i ben, bydd pawb sydd eisiau hyd yn oed “newydd ddarllen” yn aros. Ac rydym yn cofio hynny UPDATE mae gennym ni amser hir ...

Gadewch i ni ei ddiffodd yn gyflym, yna ei droi ymlaen yn gyflym!

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

UPDATE ...;

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

Yma mae'r sefyllfa eisoes yn well, mae'r amser aros yn llawer llai. Ond dim ond dwy broblem sy'n difetha'r holl harddwch:

  • ALTER TABLE ei hun yn aros am bob llawdriniaeth arall ar y bwrdd, gan gynnwys rhai hir SELECT
  • Tra bod y sbardun i ffwrdd "hedfan gan" unrhyw newid yn y bwrdd, nid hyd yn oed ein un ni. Ac ni fydd yn mynd i mewn i'r agregau, er y dylai. Trafferth!

Rheoli newidynnau sesiwn

Felly, yn y fersiwn flaenorol, fe wnaethom faglu ar bwynt sylfaenol - mae angen i ni rywsut ddysgu'r sbardun i wahaniaethu rhwng newidiadau “ein” yn y tabl ac “nid ein rhai ni”. Mae “ein un ni” yn cael ei hepgor fel y mae, ond ar “nid ein un ni” maen nhw'n cael eu sbarduno. Ar gyfer hyn gallwch chi ddefnyddio newidynnau sesiwn.

sesiwn_rôl_rôl

Darllenwch llawlyfr:

Mae'r newidyn cyfluniad hefyd yn effeithio ar y mecanwaith sbarduno sesiwn_rôl_rôl. Wedi'i alluogi heb gyfarwyddiadau ychwanegol (diofyn), bydd sbardunau yn tanio pan fydd y rôl atgynhyrchu yn "darddiad" (diofyn) neu'n "lleol". Sbardunau galluogi gan nodi ENABLE REPLICA, bydd yn gweithio dim ond os modd sesiwn presennol - "replica", a sbardunau galluogi gan nodi ENABLE ALWAYS, yn gweithio waeth beth fo'r modd atgynhyrchu presennol.

Pwysleisiaf yn arbennig nad yw'r lleoliad yn berthnasol i bawb ar unwaith, fel ALTER TABLE, ond dim ond i'n cysylltiad arbennig ar wahân. Yn gyfan gwbl, fel nad oes unrhyw gais yn sbarduno gwaith:

SET session_replication_role = replica; -- выключили триггеры
UPDATE ...;
SET session_replication_role = DEFAULT; -- вернули в исходное состояние

Cyflwr y tu mewn i'r sbardun

Ond mae'r opsiwn uchod yn gweithio ar gyfer pob sbardun ar unwaith (neu mae angen i chi "newid" sbardunau ymlaen llaw nad ydych chi am eu hanalluogi). Ac os oes angen "trowch i ffwrdd" un sbardun penodol?

Bydd hyn yn ein helpu ni newidyn sesiwn "defnyddiwr".:

Ysgrifennir enwau paramedr estyn fel a ganlyn: enw'r estyniad ac yna dot ac yna enw'r paramedr ei hun, yn debyg i enwau gwrthrychau llawn yn SQL. Er enghraifft: plpgsql.variable_conflict .
Oherwydd y gellir gosod opsiynau y tu allan i'r system mewn prosesau nad ydynt yn llwytho'r modiwl estyn priodol, mae PostgreSQL yn derbyn gwerthoedd ar gyfer unrhyw enwau gyda dwy gydran.

Yn gyntaf, rydym yn cwblhau'r sbardun, rhywbeth fel hyn:

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

Gyda llaw, gellir gwneud hyn "er elw", heb rwystro, trwy CREATE OR REPLACE ar gyfer y swyddogaeth sbardun. Ac yna yn y cysylltiad arbennig rydym yn ceiliogod "ein" newidyn:


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

Ydych chi'n gwybod am ffyrdd eraill? Rhannwch yn y sylwadau.

Ffynhonnell: hab.com

Ychwanegu sylw