Təsəvvür elə, bir kafedə işləyirsən: bir ofisiant mətbəxdə tortların ehtiyatını yoxlayır, digəri isə yeni müştəridən tort sifarişi qəbul edir. İdeal dünyada hər ikisi tortların sayına dair eyni məlumatlarla işləməlidir ki, "ikiqat bronlama" kimi səhvlər olmasın. Amma real həyatda paralel əməliyyatlar zamanı problemlər çıxa bilər.
Budur, baş verə biləcək üç əsas xoşagəlməzlik:
Dirty Read (çirkli oxuma): Bir sorğu başqa birinin etdiyi, amma hələ commit olunmamış dəyişiklikləri görür. Əgər bu dəyişikliklər rollback olunsa, birinci sorğu elə ilk müsahibəsində olan tələbə kimi saf qalacaq.
Non-Repeatable Read (təkrarlanmayan oxuma): Bir sorğu eyni məlumatı iki dəfə oxuyur, amma bu iki oxuma arasında kimsə onu dəyişir. Bu, vağzala gəlib qatar cədvəlini görmək, bir dəqiqə sonra qayıdıb qatarın ləğv olunduğunu tapmaq kimidir. Ya da pul axtaranda biletini başqası alıb :)
Phantom Read (fantom oxuma): Bir sorğu sətirlərin alt çoxluğunu görür, amma iki icra arasında kimsə yeni sətirlər əlavə edir və nəticəyə təsir edir. Bu, sanki şirkətin tenderdə uduzur, sonra sənin və merin arvadının ərizəsi istisna olmaqla bütün ərizələr ləğv olunur.
Tranzaksiya izolyasiya səviyyələri
Artıq problemləri bildiyimizə görə, PostgreSQL-in bunları həll etmək üçün verdiyi alətə baxaq — tranzaksiya izolyasiya səviyyələri. Bu, paralel tranzaksiyalar arasında qarşılıqlı əlaqə qaydalarını təyin etmək kimidir. Səviyyə nə qədər yüksəkdirsə, tranzaksiyaların bir-birinə mane olmaması üçün daha çox zəmanət var. Amma bunun əvəzində "xidmət sürəti", yəni performans azalır.
PostgreSQL-də izolyasiya səviyyələri
Read Uncommitted (Təsdiqlənməmiş məlumatların oxunması):
- Hələ commit olunmamış dəyişiklikləri oxumağa imkan verir (bəli, bu tam çirkli oxuma effektidir).
- PostgreSQL-də bu səviyyə əslində
Read Committedkimi işləyir, yəni tam dəstəklənmir. PostgreSQL bunu reallaşdırmaqdan imtina edir, çünki bu yanaşma çox etibarsızdır.
Read Committed (Təsdiqlənmiş dəyişikliklərin oxunması):
- Çirkli oxumanı qarşısını alır.
- Tranzaksiya yalnız əmrin icrası anında commit olunmuş məlumatları görür.
- Amma
Non-Repeatable ReadvəPhantom Readmümkündür.
Repeatable Read (Təkrarlanan oxuma):
- Oxuduğun məlumatlar tranzaksiya boyunca dəyişməz qalacağına zəmanət verir.
- Çirkli oxuma və təkrarlanmayan oxumanı qarşısını alır.
- Amma fantom sətirlər hələ də mümkündür.
Serializable (Səriləşdirilə bilən):
- Tranzaksiyaların sanki ardıcıl, bir-birinin arxasınca icra olunduğu kimi işləməsinə zəmanət verir.
- Bütün üç problemi qarşısını alır: çirkli oxuma, təkrarlanmayan oxuma və fantom sətirlər.
- Ən sərt — və ən yavaş — izolyasiya səviyyəsidir.
Niyə tranzaksiya izolyasiyası vacibdir?
İndi təsəvvür elə, minlərlə istifadəçi eyni anda sifariş verməyə çalışan bir onlayn mağaza bazası var. Düzgün qurulmamış izolyasiya səviyyəsi ilə "yoxa çıxan" məhsullardan tutmuş təkrarlanan sifarişlərə qədər bir sürü konfliktlə qarşılaşa bilərsən.
Düzgün izolyasiya səviyyəsi seçimi paralel tranzaksiyaların idarə olunmasına kömək edir, performans və məlumat bütövlüyü arasında balans yaradır. Məsələn:
- Analitik sistemlərdə adətən minimal izolyasiya səviyyələri seçilir (məsələn, Read Committed), çünki məlumat dəqiqliyi həmişə kritik olmur.
- Maliyyə sistemlərində isə səhvlərin və ya əməliyyatların təkrarlanmasının qarşısını almaq üçün Serializable səviyyəsi üstünlük verilir.
İzolyasiya səviyyələrinin tətbiq nümunələri
- Read Committed
Bu səviyyə təmin edir ki, heç vaxt rollback oluna biləcək məlumatı oxumayacaqsan.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
-- Hesab məlumatını oxu.
SELECT balance FROM accounts WHERE account_id = 1;
-- Başqa bir tranzaksiya balansı yeniləsə, bu məlumat dərhal yenilənəcək.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;
- Repeatable Read
Bu səviyyə zəmanət verir ki, oxuduğun məlumat tranzaksiya boyunca sənin üçün dəyişməz qalacaq.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
-- Hesab məlumatını oxu.
SELECT balance FROM accounts WHERE account_id = 1;
-- Başqa bir tranzaksiya bu balansı yeniləsə belə, sən dəyişiklikləri görməyəcəksən.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;
- Serializable
Bu səviyyədə tranzaksiya sanki sistemdə tək işləyirmiş kimi davranır.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- Hesab məlumatını oxu.
SELECT balance FROM accounts WHERE account_id = 1;
-- Bu məlumatı dəyişməyə çalışan başqa hər hansı tranzaksiya, sənin tranzaksiyan bitənə qədər bloklanacaq.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;
İzolyasiya səviyyəsini necə seçmək olar?
İzolyasiya səviyyəsinin seçimi tələblərindən asılıdır:
- Əgər sürət dəqiqlikdən vacibdirsə və fantom sətirlərə dözə bilirsənsə —
Read Committedseç. - Dəqiqlik vacibdirsə, amma hələ də yüksək performans istəyirsənsə —
Repeatable Readistifadə et. - Əgər 100% düzgünlük zəmanəti lazımdırsa, hətta sürət bahasına olsa belə — sənə
Serializableuyğundur.
Diqqətli ol! Sərt izolyasiya səviyyələri bloklanmalara və sistemin performansının azalmasına səbəb ola bilər. Ən ağıllı yol — performans və məlumat uyğunluğu arasında kompromis tapmaqdır.
GO TO FULL VERSION