Beləliklə, əziz tələbələr, artıq trigger-lər, onların növləri, necə işlədikləri barədə məlumatınız var və hətta müxtəlif tapşırıqları yerinə yetirmək üçün onları yaratmağı da öyrənmisiniz. Amma proqramlaşdırmada tez-tez olduğu kimi, nəyi edə biləcəyini bilmək vacibdir, amma nəyi etməmək lazım olduğunu bilmək də az önəmli deyil. Bu gün biz trigger-lərlə işləyərkən developer-lərin buraxdığı tipik səhvləri araşdıracağıq ki, siz onlardan qaça biləsiniz və özünüzə bir neçə saat, bəlkə də günlər qənaət edəsiniz debugging-ə.
Trigger rekursiyası: trigger özünü çağırır
Bu, yəqin ki, yeni başlayanların ən məşhur səhvidir. Təsəvvür elə ki, bir trigger yaratmısan, hansı ki, cədvəldəki sütunlardan birini, məsələn, last_modified-i yeniləyir. Amma bu dəyişiklik baş verən kimi, həmin update əməliyyatı yenidən trigger-i işə salır. Bu sonsuz döngüdür və nəticədə server stack overflow ilə yıxılır.
Nümunə:
CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
-- last_modified sahəsini yeniləyirik
UPDATE my_table
SET last_modified = NOW()
WHERE id = NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER after_update
AFTER UPDATE ON my_table
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();
Burada nə səhv gedir? UPDATE əməliyyatı funksiyanın içində həmin trigger-i yenidən çağırır. Vəssalam, sonsuz döngü alırıq.
Necə qaçmaq olar:
OLD dəyişənindən istifadə elə və dəyərləri müqayisə elə, dəyişiklik etməzdən əvvəl:
CREATE OR REPLACE FUNCTION update_last_modified_safe()
RETURNS TRIGGER AS $$
BEGIN
-- Dəyərin dəyişib-dəyişmədiyini yoxlayırıq
IF NEW.last_modified IS DISTINCT FROM OLD.last_modified THEN
NEW.last_modified = NOW();
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Əmin ol ki, trigger-in içində lazımsız əməliyyatlar çağırmırsan.
OLD və NEW-un səhv istifadəsi
Bu dəyişənlər trigger-lərlə işləyəndə sənin əsl dostundur, amma təcrübəsiz əllərdə başağrısına çevrilə bilər. OLD sətirdə dəyişiklikdən əvvəlki məlumatı saxlayır, NEW isə dəyişiklikdən sonra saxlanacaq məlumatı.
Səhv adətən dəyişənləri düzgün başa düşməyəndə və ya onlar olmayan yerdə istifadə etməyə çalışanda baş verir. Məsələn, əgər BEFORE INSERT trigger-i ilə işləyirsənsə, OLD əlçatmaz olacaq — çünki sətir hələ indi yaranır.
Səhv nümunəsi:
-- Bu səhv verəcək, çünki OLD insert zamanı mövcud deyil
CREATE OR REPLACE FUNCTION log_inserts()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit_log (old_data, new_data)
VALUES (OLD.my_column, NEW.my_column);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Necə qaçmaq olar:
Diqqətlə seç, harada OLD, harada NEW istifadə edirsən:
OLDyalnızUPDATEvəDELETEəməliyyatlarında mövcuddur.NEWisəINSERTvəUPDATEəməliyyatlarında mövcuddur.
Bir əməliyyata bir neçə trigger
PostgreSQL-də bir əməliyyat və cədvəl üçün bir neçə trigger yarada bilərsən. Bu, rahat imkan kimi görünür, amma əslində trigger-lər bir-biri ilə konfliktə girəndə və ya eyni məlumatı dəyişəndə xaosa səbəb ola bilər.
Nümunə:
-- Trigger 1
CREATE OR REPLACE FUNCTION trigger_one()
RETURNS TRIGGER AS $$
BEGIN
-- Trigger 1-in məntiqi
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger 2
CREATE OR REPLACE FUNCTION trigger_two()
RETURNS TRIGGER AS $$
BEGIN
-- Trigger 2-in məntiqi
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- İki trigger-in yaradılması
CREATE TRIGGER trigger_one AFTER INSERT ON my_table EXECUTE FUNCTION trigger_one();
CREATE TRIGGER trigger_two AFTER INSERT ON my_table EXECUTE FUNCTION trigger_two();
Hər iki trigger my_table-a sətir əlavə olunanda işləyəcək. Əgər onların məntiqi düzgün sinxronizasiya olunmayıbsa, nəticələr gözlənilməz ola bilər.
Necə qaçmaq olar:
- Trigger arxitekturasını əvvəlcədən planlaşdır.
- Əgər trigger-lər eyni məntiqə toxunursa, onları bir trigger-də birləşdir.
Performans problemləri
Trigger-lər hər bir əməliyyata əlavə hesablama gətirir. Əgər trigger-ləri çoxlu əməliyyat və ya böyük cədvəllərdə istifadə edirsənsə, bu, performansın ciddi şəkildə aşağı düşməsinə səbəb ola bilər.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION heavy_trigger_function()
RETURNS TRIGGER AS $$
BEGIN
-- Hər sətir yenilənəndə ağır əməliyyat
PERFORM some_heavy_query();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER performance_killer AFTER UPDATE ON huge_table EXECUTE FUNCTION heavy_trigger_function();
Necə qaçmaq olar:
- Trigger-də icra olunan məntiqi minimuma endir. Əgər ağır əməliyyat lazımdırsa, onu background-da yerinə yetirməyi düşün.
- Trigger-in icrasını məhdudlaşdırmaq üçün
WHENşərtindən istifadə et:
CREATE TRIGGER optimized_trigger
AFTER UPDATE ON my_table
WHEN (OLD.column_name IS DISTINCT FROM NEW.column_name)
EXECUTE FUNCTION light_function();
Trigger-lər və tranzaksiyalar
Trigger-lər sənin sorğunun başladığı tranzaksiyanın içində icra olunur. Əgər trigger-in içində səhv baş verərsə, bütün tranzaksiya rollback olacaq. Bəzi hallarda bu faydalı ola bilər, amma error handling düzgün qurulmayıbsa, gözlənilməz problemlərə səbəb ola bilər.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION error_prone_trigger()
RETURNS TRIGGER AS $$
BEGIN
-- Səhv yaradılır
RAISE EXCEPTION 'Nəsə səhv getdi!';
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Əgər bu trigger işləsə, əsas sorğunun tranzaksiyası rollback olacaq.
Necə qaçmaq olar:
Trigger-lərdə error handling əlavə et ki, əsas tranzaksiyaya təsiri minimum olsun:
CREATE OR REPLACE FUNCTION safe_trigger()
RETURNS TRIGGER AS $$
BEGIN
BEGIN
-- Səhv yarada biləcək kod
INSERT INTO another_table VALUES (NEW.data);
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Səhv baş verdi, amma biz onu sakitcə həll etdik.';
END;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Praktik tövsiyələr
Trigger-ləri maksimum sadə saxla. Əgər sənə elə gəlirsə ki, trigger çox böyük və ya mürəkkəbdir, yəqin ki, onu ayrıca funksiyalara bölmək və ya məntiqi yenidən düşünmək lazımdır.
Trigger-ləri həmişə az miqdarda məlumatda test et. Trigger-i kritik cədvələ qoşmazdan əvvəl onu test mühitində yoxla.
Trigger-ləri sənədləşdir. Bir neçə aydan sonra sən və ya komanda yoldaşların trigger-in niyə yaradıldığını unuda bilərsiz. Aydın sənədləşmə əlavə başağrısından xilas edəcək.
Trigger-lərdən mümkün qədər app səviyyəsində həll edilə bilən məsələlər üçün istifadə etmə. Trigger-lər avtomatlaşdırma üçün əladır, amma kompleks biznes məntiqi üçün istifadə etsən, gələcəkdə problemlər çıxara bilər.
Performansa nəzarət et. Trigger-lərin database performansına təsirini daim monitor et, xüsusilə məlumat və yük artanda.
Bu məsləhətlər və gün ərzində qazandığın biliklərlə sən artıq təkcə trigger-lər yaratmağa yox, həm də düzgün, effektiv və sürprizsiz işləyən trigger-lər yazmağa hazırsan.
GO TO FULL VERSION