PostgreSQL Antipatterns: breyttu gögnum framhjá kveikju

Fyrr eða síðar standa margir frammi fyrir því að þurfa að laga eitthvað í töflunni í stórum stíl. ég hef núþegar segðu mér hvernig á að gera það betur, og hvernig - það er betra að gera það ekki. Í dag mun ég tala um annan þátt fjöldauppfærslunnar - um kveikjur.

Til dæmis, á borði þar sem þú þarft að laga eitthvað, hangir vondur kveikja ON UPDATE, flytja allar breytingar til sumra heildar. Og þú þarft að uppfæra allt (t.d. frumstilla nýtt reit) svo vandlega að þessi söfnun verði ekki fyrir áhrifum.

Við skulum bara slökkva á kveikjunum!

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

Reyndar, það er allt - allt hangir.

Vegna ALTER TABLE leggur Aðgangur eingöngu- lás sem enginn hleypur undir samhliða, jafnvel einfaldur SELECT, mun ekki geta lesið neitt úr töflunni. Það er, þar til þessum viðskiptum er lokið munu allir sem vilja „bara lesa“ bíða. Og við minnumst þess UPDATE við eigum langan...

Slökkum fljótt á því og kveikjum svo fljótt á því!

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

UPDATE ...;

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

Hér er ástandið nú þegar betra, biðtíminn mun styttri. En aðeins tvö vandamál spilla allri fegurðinni:

  • ALTER TABLE sjálft bíður eftir öllum öðrum aðgerðum á borðinu, líka löngum SELECT
  • Á meðan slökkt er á kveikjunni, „fljúga framhjá“ hvaða breytingu sem er í töflunni, ekki einu sinni okkar. Og það mun ekki komast inn í heildina, þó það ætti að gera það. Vandræði!

Umsjón með lotubreytum

Svo, í fyrri útgáfu, lentum við á grundvallaratriði - við þurfum einhvern veginn að kenna kveikjuna til að greina „okkar“ breytingar á töflunni frá „ekki okkar“. „Okkar“ er sleppt eins og það er, en á „ekki okkar“ eru þeir ræstir. Fyrir þetta geturðu notað lotubreytur.

session_replication_role

Lestu handbók:

Kveikjubúnaðurinn hefur einnig áhrif á stillingarbreytuna session_replication_role. Virkt án frekari leiðbeininga (sjálfgefið), kveikja verður þegar afritunarhlutverkið er „uppruni“ (sjálfgefið) eða „staðbundið“. Kveikjur virkjaðar með því að tilgreina ENABLE REPLICA, mun aðeins virka ef núverandi lotuhamur - "eftirmynd", og kveikjur virkjaðar með því að tilgreina ENABLE ALWAYS, mun virka óháð núverandi afritunarham.

Ég mun sérstaklega leggja áherslu á að stillingin á ekki við um allt-allt í einu, eins og ALTER TABLE, en aðeins að sérstökum sérstökum tengingum okkar. Alls, svo að ekkert forrit kveiki á vinnu:

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

Ástand inni í kveikju

En valkosturinn hér að ofan virkar fyrir alla kveikjur í einu (eða þú þarft að „skipta um“ kveikjum fyrirfram sem þú vilt ekki slökkva á). Og ef við þurfum „slökkva“ á einum tilteknum kveikju?

Þetta mun hjálpa okkur „notandi“ setubreytu:

Framlengingarfæribreytuheiti eru skrifuð sem hér segir: framlengingarheitið á eftir punkti og síðan færibreytanafnið sjálft, svipað og fullum nöfnum hluta í SQL. Til dæmis: plpgsql.variable_conflict.
Þar sem hægt er að stilla valkosti utan kerfis í ferlum sem hlaða ekki samsvarandi viðbótareiningu, samþykkir PostgreSQL gildi fyrir öll nöfn með tveimur hlutum.

Fyrst breytum við kveikjunni, eitthvað á þessa leið:

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

Við the vegur, þetta er hægt að gera "í hagnaðarskyni", án þess að loka, í gegnum CREATE OR REPLACE fyrir kveikjuaðgerðina. Og svo í sérstöku sambandi tökum við „okkar“ breytu:


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

Kanntu aðrar leiðir? Deildu í athugasemdum.

Heimild: www.habr.com

Bæta við athugasemd