PostgreSQL اينٽي پيٽرن: ٽرگر کي پاس ڪندي ڊيٽا کي تبديل ڪريو

جلدي يا بعد ۾، ڪيترن ئي ماڻهن کي ميز جي رڪارڊ ۾ وڏي پيماني تي ڪجهه درست ڪرڻ جي ضرورت آهي. مون وٽ اڳ ۾ ئي آهي مون کي ٻڌايو ته اهو بهتر ڪيئن ڪجي، ۽ ڪيئن - اهو بهتر ناهي ته اهو نه ڪجي. اڄ آئون ماس اپڊيٽ جي ٻئي پهلو بابت ڳالهائيندس - محرڪن جي باري ۾.

مثال طور، هڪ ميز تي جنهن ۾ توهان کي ڪجهه درست ڪرڻ جي ضرورت آهي، هڪ برائي ٽريگر پھان ٿو 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، صرف ڪم ڪندو جيڪڏهن موجوده سيشن موڊ - "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

تبصرو شامل ڪريو