Antipatterns 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
  • در حالی که ماشه خاموش است هر تغییری "پرواز کن". در جدول، نه حتی ما. و در مجموعات وارد نمی شود، اگرچه باید. مشکل!

مدیریت متغیرهای جلسه

بنابراین، در نسخه قبلی، ما به یک نکته اساسی برخورد کردیم - باید به نحوی به ماشه آموزش دهیم که تغییرات "ما" در جدول را از "غیر ما" تشخیص دهد. "مال ما" همانطور که هست نادیده گرفته می شود، اما در "مال ما نیست" آنها فعال می شوند. برای این شما می توانید استفاده کنید متغیرهای جلسه.

session_replication_role

خواندن کتابچه راهنمای:

مکانیسم ماشه نیز تحت تأثیر متغیر پیکربندی قرار می گیرد session_replication_role. بدون دستورالعمل اضافی (پیش‌فرض) فعال می‌شود، هنگامی که نقش تکراری «مبدع» (پیش‌فرض) یا «محلی» باشد، تریگرها فعال می‌شوند. راه‌اندازها با مشخص کردن فعال می‌شوند 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

اضافه کردن نظر