PostgreSQL Antipatterns: տվյալները փոխում ենք անջատիչից շրջանցելով

Ավելի վաղ թե ուշ շատերը բախվում են անհրաժեշտությանը մաքսայինորեն ինչ-որ բան շտկել աղյուսակի գրառումներում։ Ես արդեն պատկերացրեցի, թե ինչպես անել լավ, իսկ ինչպես՝ ավելի լավ չէ։ Ա TODAY ես պատմում եմ երկրորդ ասպեկտի մասին ` տրիգերների գործում.

Օրինակ, այն աղյուսակում, որտեղ դուք պետք է ինչ-որ բան շտկեք, կախված է չար թրի ON UPDATE, որը տեղափոխում է բոլոր փոփոխությունները ինչ-որ ագրեգատների։ Իսկ ձեզ հարկավոր է բոլորովին վերաբերել (новое поле проинициализировать, օրինակ) այնքան զգուշորեն, որ այդ ագրեգատները չկտրվեն։

Եկեք պարզապես անջատենք թիրաբարները!

BEGIN;
  ALTER TABLE ... DISABLE TRIGGER ...;
  UPDATE ...; -- здесь долго-долго
  ALTER TABLE ... ENABLE TRIGGER ...;
COMMIT;

Բանն այն է, որ այստեղ էլ ամեն ինչ՝ բոլորը արդեն կախված է.

Որովհետև ALTER TABLE ներգրավել է AccessExclusive-արգելափակումը, որի տակ ոչ մեկը զուգընթաց իրականացնող, նույնիսկ պարզ SELECT, ոչինչ աղյուսակից կարդալ չի կարող։ Այժմ այս գործառնությունը չի ավարտվի, բոլոր ցանկացողները նույնիսկ «միայն կարդալ» սպասելու են։ Եվ մենք հիշում ենք, որ UPDATE մեր մոտ բացատրող է…

Եկեք այնպես արագ անջատենք, հետո արագ կավելացնենք!

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

UPDATE ...;

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

Այստեղ իրավիճակը արդեն լավ է, սպասման ժամանակը զգալիորեն նվազում է։ Բայց երկու խնդիրները վատացնում են ողջ գեղեցկությունը․

  • ALTER TABLE նա սպասում է բոլոր մյուս գործողություններին աղյուսակի վրա, ներառյալ երկար SELECT
  • Մինչդեռ թրիգերը անջատված է, «անցնում է որևէ փոփոխություն» աղյուսակում, նույնիսկ մեր։ Եվ ագրեգատներ, ինչ-որ կերպ չի մտնի, ինչ-որ կերպ պետք է։ Վշտություն!

Ն SESSION փոփոխականների կառավարում

Այդ իսկ պատճառով, նախորդ տարբերակում մենք հանդիպեցինք հիմնարար կետին՝ պետք է ինչ-որ ձևով ուսուցնենք թրիգերին տարբերակել «մեր» փոփոխությունները աղյուսակում «չմեր»։ «Մեր» թողնել այնպես, ինչպես կա, իսկ «չմեր»՝ գործողության ժամանակ։ Bunun için可以 воспользоваться ն SESSION փոփոխականներով.

session_replication_role

Կարդում ենք հանձնարա:

Թրի գոտու աշխատման մեխանիզմին նաև ազդում է կոնֆիգուրացիոն փոփոխականը։ Հավաստվածները, որ առանց լրացուցիչ ցուցումների (առանձնապես), թրիգերները աշխատում են, երբ կրկնության դերակատարությունը՝ «origin» (առանձնապես) կամ «local»։ Թրիգերները, որոնք ակտիվանում են session_replication_roleENABLE REPLICA , կաշխատեն միայն եթենշանակված տվյալ դիրքերը — «replica», իսկ թրիգերները, որոնք ակտիվանում են ENABLE ALWAYS , կաշխատեն անկախ տվյալ կրկնության իրավիճակներից։Հատուկ ընդգծում եմ, որ կարգավորումը վերաբերում է ոչ բոլորին, ինչպես

, այլ միայն մեր առանձնահատուկ մասնագիտությանը։ Այժմ, որպեսզի ոչ մի իրական կիրառական կամ մեխանիկա չաշխատեն որպես՝ ALTER TABLESET session_replication_role = replica; -- անջատվեց թրիգերները UPDATE ...; SET session_replication_role = DEFAULT; -- վերադարձնել սկզբնական վիճակ

Թրիգերի մեջ պայմանը

Բայց վերոնշյալ տարբերակն աշխատում է բոլոր թրիգերի վրա միասին (կամ պետք է «ալտերել» առաջարժեքներին, որոնք ցանկալի չէին անջատել)։ Իսկ եթե մեզ հարկավոր է

«անգ միասնական» մեկ կոնկրետ թրիգեր Այվսկեն մեզ կօգնի?

... «օգտագործողի» սեսիայի փոփոխական:

Հարաբերական պարամետրերի անունները գրանցվում են հետևյալ կերպ. ընդլայնման անուն, կետ և հետո իսկական պարամետրի անուն, ինչպես SQL-ում առարկաների πλήρες անունը։ Օրինակ՝ plpgsql.variable_conflict.
Քանի որ համակարգից դուրս պարամետրեր կարող են սահմանվել այն գործընթացներում, որոնք չեն բեռնվում համապատասխան ընդլայնման մոդուլ, PostgreSQL-ն ընդունում է քանի որ երկու բաղադրիչ ունեցող ցանկացած անվան համար արժեքները.

Առաջին հերթին ավարտում ենք թելակի ծեսը, մոտավորապես այնպես՝

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

Մեծ օրինակի շնորհիվ, դա կարելի է անել «սկսած», առանց բլոկավորման, միջոցով ՍՏԵՊՈՒ ԶՎԻՏԻՆ Առաջին առանցքային ֆունկցիայի համար։ Իսկ հետո հատուկ կապի միջոցով ակտիվացնում ենք «մեր» փոփոխականը՝


SET mycfg.my_table_convert_process = 'TRUE';
UPDATE ...;
SET mycfg.my_table_convert_process = ''; -- վերադարձել էլեկտրական վիճակին

Գիտե՞ք այլ եղանակներ։ կիսվեք մեկնաբանություններում։

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster