PostgreSQL Antipatterns: ප්‍රේරකයක් මගහැර දත්ත වෙනස් කරන්න

වැඩි කල් යන්නට මත්තෙන්, බොහෝ දෙනෙක් වගු වාර්තාවල යමක් විශාල වශයෙන් සවි කිරීමේ අවශ්‍යතාවයට මුහුණ දෙති. මම දැනටමත් තියෙනවා එය වඩා හොඳින් කරන්නේ කෙසේදැයි මට කියන්න, සහ කෙසේද - එය නොකිරීමට වඩා හොඳය. අද මම මහා යාවත්කාලීනයේ දෙවන අංගය ගැන කතා කරමි - ප්‍රේරක ගැන.

උදාහරණයක් ලෙස, ඔබට යමක් නිවැරදි කිරීමට අවශ්‍ය මේසයක් මත, නපුරු ප්‍රේරකයක් එල්ලී ඇත ON UPDATE, සියලු වෙනස්කම් සමහර එකතු කිරීම් වෙත මාරු කිරීම. තවද ඔබට මෙම සමස්ථයන්ට බලපෑමක් නොවන පරිදි ප්‍රවේශමෙන් සියල්ල යාවත්කාලීන කළ යුතුය (උදාහරණයක් ලෙස නව ක්ෂේත්‍රයක් ආරම්භ කරන්න).

අපි ප්‍රේරක අක්‍රිය කරමු!

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

ඇත්ත වශයෙන්ම, එපමණයි - සියල්ල එල්ලෙමින් තිබේ.

මොකද ALTER TABLE පනවයි ප්‍රවේශය සුවිශේෂී- කිසිවෙකු සමාන්තරව ධාවනය නොවන අගුලක්, සරල එකක් පවා SELECT, මේසයෙන් කිසිවක් කියවීමට නොහැකි වනු ඇත. එනම්, මෙම ගනුදෙනුව අවසන් වන තුරු, "හුදෙක් කියවීමට" පවා අවශ්ය සියලු දෙනා බලා සිටිනු ඇත. ඒ වගේම අපිට ඒක මතකයි UPDATE අපට දිගු ...

අපි ඉක්මනින් එය නිවා දමමු, පසුව ඉක්මනින් එය සක්රිය කරන්න!

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

UPDATE ...;

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

මෙන්න තත්වය දැනටමත් වඩා හොඳ ය, පොරොත්තු කාලය බෙහෙවින් අඩු ය. නමුත් ගැටළු දෙකක් පමණක් සියලු අලංකාරය නරක් කරයි:

  • ALTER TABLE දිගු ඒවා ඇතුළුව මේසය මත ඇති අනෙකුත් සියලුම මෙහෙයුම් සඳහා එයම බලා සිටී SELECT
  • ප්‍රේරකය ක්‍රියාවිරහිතව තිබියදී ඕනෑම වෙනසක් "පියාසර කරන්න" මේසය තුළ, අපගේ පවා නොවේ. එය තිබිය යුතු වුවද, එය සමස්ථයට ඇතුල් නොවනු ඇත. කරදරයක්!

සැසි විචල්‍ය කළමනාකරණය

එබැවින්, පෙර අනුවාදයේ, අපි මූලික කරුණක් මත පැකිළුණා - වගුවේ “අපගේ” වෙනස්කම් “අපගේ නොවේ” වෙතින් වෙන්කර හඳුනා ගැනීමට අපි කෙසේ හෝ ප්‍රේරකයට ඉගැන්විය යුතුය. "අපගේ" යන්න මඟ හැර ඇත, නමුත් "අපගේ නොවේ" මත ඒවා ක්‍රියා විරහිත වේ. මේ සඳහා ඔබට භාවිතා කළ හැකිය සැසි විචල්යයන්.

සැසිය_ප්‍රතිනිර්මාණ_භූමිකාව

කියවන්න අත්පොත:

ප්‍රේරක යාන්ත්‍රණය ද වින්‍යාස විචල්‍යය මගින් බලපායි සැසිය_ප්‍රතිනිර්මාණ_භූමිකාව. අමතර උපදෙස් (පෙරනිමිය) නොමැතිව සක්‍රීය කර ඇති අතර, ප්‍රේරක අනුරූකරණ භූමිකාව "සම්භවය" (පෙරනිමිය) හෝ "දේශීය" වූ විට ක්‍රියා කරයි. ප්‍රේරක නියම කිරීමෙන් සක්‍රීය කර ඇත ENABLE REPLICA, වැඩ කරන්නේ නම් පමණි වත්මන් සැසි මාදිලිය - "ප්‍රතිරූපය", සහ ප්‍රේරක නියම කිරීමෙන් සක්‍රීය කර ඇත ENABLE ALWAYS, වත්මන් අනුවර්තන මාදිලිය නොසලකා වැඩ කරනු ඇත.

මෙම සැකසුම සියල්ලට එකවර අදාළ නොවන බව මම විශේෂයෙන් අවධාරණය කරමි ALTER TABLE, නමුත් අපගේ වෙනම විශේෂ සම්බන්ධතාවයකට පමණි. සමස්තයක් වශයෙන්, කිසිදු යෙදුමක් ක්‍රියා නොකරයි.

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

මාර්ගය වන විට, මෙය "ලාභය සඳහා", අවහිර කිරීමකින් තොරව, හරහා සිදු කළ හැකිය CREATE OR REPLACE ප්‍රේරක කාර්යය සඳහා. ඉන්පසු විශේෂ සම්බන්ධතාවයේදී අපි "අපගේ" විචල්‍යය කුකුළා:


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

ඔබ වෙනත් ක්රම දන්නවාද? අදහස් බෙදාගන්න.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න