پوسٹگری ایس کیو ایل اینٹی پیٹرنز: ٹرگر کو نظرانداز کرتے ہوئے ڈیٹا کو تبدیل کریں۔

جلد یا بدیر، بہت سے لوگوں کو ٹیبل ریکارڈز میں بڑے پیمانے پر کچھ ٹھیک کرنے کی ضرورت کا سامنا کرنا پڑتا ہے۔ میں نے پہلے ہی مجھے بتائیں کہ یہ کیسے بہتر ہے، اور کیسے - یہ نہ کرنا بہتر ہے۔ آج میں بڑے پیمانے پر اپ ڈیٹ کے دوسرے پہلو کے بارے میں بات کروں گا - محرکات کے بارے میں.

مثال کے طور پر، ایک میز پر جس میں آپ کو کچھ ٹھیک کرنے کی ضرورت ہے، ایک بری ٹرگر لٹکا ہوا ہے۔ 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; -- вернули в исходное состояние

ٹرگر کے اندر کی حالت

لیکن اوپر والا آپشن ایک ساتھ تمام ٹرگرز کے لیے کام کرتا ہے (یا آپ کو پہلے سے "متبادل" ٹرگرز کرنے کی ضرورت ہے جسے آپ غیر فعال نہیں کرنا چاہتے ہیں)۔ اور اگر ہمیں ضرورت ہے۔ ایک مخصوص ٹرگر کو "آف" کریں۔?

یہ ہماری مدد کرے گا۔ "صارف" سیشن متغیر:

ایکسٹینشن پیرامیٹر کے نام اس طرح لکھے گئے ہیں: ایکسٹینشن کا نام جس کے بعد ایک ڈاٹ اور پھر پیرامیٹر کا نام، ایس کیو ایل میں مکمل آبجیکٹ کے ناموں کی طرح۔ مثال کے طور پر: 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

نیا تبصرہ شامل کریں