Gəlin bir də transaksiyaların növlərinə baxaq! Database transaksiyaları dünyasında üç əsas "pis oğlan" var ki, gününüzü korlaya bilər: Dirty Read, Non-Repeatable Read və Phantom Read. Bu "anomaliyalar" transaksiyaların kifayət qədər izolə olunmamasından yaranır. Bu gün baxacağıq ki, bu pis oğlanlar kimdir, necə işləyirlər və ən əsası — onlarla necə mübarizə aparmaq olar.
Misallara keçməzdən əvvəl, gəlin yadımıza salaq ki, bunlar nə deməkdir.
Dirty Read (Çirkli oxuma):
Sən dəyişdirilmiş məlumatı oxuyursan, amma həmin məlumatı dəyişən transaksiyanın hələCOMMITolunmayıb və ya, daha da pis,ROLLBACKoluna bilər. Bu elə bil ki, dostuna pul göndərirsən, balansına baxırsan və görürsən ki, kasıbsan, amma sonra fikrini dəyişib pulu özünə qaytarırsan. Sehr!Non-Repeatable Read (Təkrarlanmayan oxuma):
Bir transaksiyada eyni məlumatı iki dəfə oxuyursan, amma bu iki oxuma arasında başqa bir transaksiya həmin məlumatı dəyişir və sən iki fərqli nəticə görürsən. Bu elə bil ki, pasportunda doğum tarixinə baxırsan, sonra onu dostuna verirsən, o da rəqəmləri dəyişir, sən bir də baxırsan və doğum tarixini dəyişmiş görürsən.Phantom Read (Fantom oxuma):
Eyni sorğunu iki dəfə edirsən, amma ikinci dəfə başqa bir transaksiya əlavə sətir əlavə edib və sən artıq əlavə sətrləri görürsən. Bu elə bil ki, otaqdakı adamları sayırsan, kimsə gizlicə əlavə dostlar gətirir.
Dirty Read problemi
Tutaq ki, bizdə accounts cədvəli var:
CREATE TABLE accounts (
account_id SERIAL PRIMARY KEY,
owner TEXT NOT NULL,
balance NUMERIC(10, 2) NOT NULL
);
INSERT INTO accounts (owner, balance) VALUES ('Alice', 1000), ('Bob', 500);
Transaksiya 1 balansı dəyişir, amma hələ bitməyib, Transaksiya 2 isə eyni anda bu məlumatı oxumağa çalışır.
Transaksiya 1:
BEGIN;
UPDATE accounts SET balance = balance - 200 WHERE owner = 'Alice';
-- Alice-in balansı oldu 800, amma transaksiyanın sonu hələ gəlməyib.
Transaksiya 2:
BEGIN;
SELECT balance FROM accounts WHERE owner = 'Alice'; -- Balansı görürük: 800 (çirkli oxuma).
ROLLBACK; -- Transaksiya 1 geri qaytarılır.
İndi Transaksiya 2 səhv məlumatla işləyir, çünki Transaksiya 1 dəyişiklikləri ləğv etdi. Bunu READ COMMITTED isolation səviyyəsi ilə həll etmək olar, hansı ki, təsdiqlənməmiş transaksiyaların dəyişikliklərini görməyə imkan vermir.
Non-Repeatable Read problemi
Təsəvvür et ki, Transaksiya 1 məlumatı oxuyur, başqa bir transaksiya onu dəyişir və Transaksiya 1 yenidən oxuyur. Məlumat artıq fərqlidir.
Transaksiya 1:
BEGIN;
SELECT balance FROM accounts WHERE owner = 'Bob'; -- Balansı görürük: 500.
Transaksiya 2 paralel olaraq:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE owner = 'Bob';
COMMIT;
Transaksiya 1 yenidən:
SELECT balance FROM accounts WHERE owner = 'Bob'; -- Balansı görürük: 400.
COMMIT;
Gördün, bir transaksiyanın içində məlumat dəyişdi. Real həyatda bu, məsələn, maliyyə hesabatlarında kritik ola bilər. Bunu daha yüksək isolation səviyyəsi ilə həll etmək olar, məsələn, REPEATABLE READ.
Phantom Read problemi
Tutaq ki, bizdə orders cədvəli var:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer TEXT NOT NULL,
total NUMERIC(10, 2) NOT NULL
);
INSERT INTO orders (customer, total) VALUES ('Alice', 100), ('Bob', 200);
Transaksiya 1 sifarişlərin sayını sayır, başqa bir transaksiya yeni sifariş əlavə edir və Transaksiya 1 yenidən sayır.
Transaksiya 1:
BEGIN;
SELECT COUNT(*) FROM orders; -- Görürük: 2.
Transaksiya 2 paralel olaraq:
BEGIN;
INSERT INTO orders (customer, total) VALUES ('Charlie', 300);
COMMIT;
Transaksiya 1 yenidən:
SELECT COUNT(*) FROM orders; -- Görürük: 3. Yeni "fantom" sifariş gəldi!
COMMIT;
Fantom oxumanı aradan qaldırmaq üçün SERIALIZABLE isolation səviyyəsi lazımdır, hansı ki, nəticəyə təsir edən paralel dəyişiklikləri tam bloklayır.
Anomaliyaların qarşısını alma yolları
Isolation səviyyələri vs. Anomaliyalar
| Isolation səviyyəsi | Dirty Read |
Non-Repeatable Read |
Phantom Read |
|---|---|---|---|
Read Uncommitted |
❌ Bəli | ❌ Bəli | ❌ Bəli |
Read Committed |
✅ Xeyr | ❌ Bəli | ❌ Bəli |
Repeatable Read |
✅ Xeyr | ✅ Xeyr | ❌ Bəli |
Serializable |
✅ Xeyr | ✅ Xeyr | ✅ Xeyr |
Doğru isolation səviyyəsini necə seçmək olar?
- Əgər məlumatlara tez çıxış lazımdır və anomaliyalar kritik deyil (məsələn, köhnəlmiş məlumatlar üzərində analitika üçün) —
READ COMMITTEDistifadə et. - Əgər bir transaksiyanın içində məlumatın sabitliyi vacibdirsə —
REPEATABLE READistifadə et. - Əgər maksimum izolasiya və konsistentlik lazımdırsa —
SERIALIZABLEseç. Unutma: performans aşağı düşə bilər.
Praktiki tövsiyələr
Transaksiyaları sənin vəziyyətinə uyğun isolation səviyyəsi ilə istifadə et. Məsələn:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT ...;
COMMIT;
İndekslər əlavə et ki, cədvəllərin bloklanmasını azaldasın və sorğular daha sürətli işləsin.
Optimallaşdırılmış sorğulardan istifadə et ki, uzunmüddətli bloklanmalardan qaçasan, xüsusilə SERIALIZABLE səviyyəsində.
Xüsusi səhvlər və onlardan necə qaçmaq olar
Bəzən düzgün seçilməmiş isolation səviyyəsi konfliktlərə və performansın aşağı düşməsinə səbəb olur. Məsələn, çoxlu paralel transaksiyaların olduğu sistemdə SERIALIZABLE istifadə etmək bloklanmalara və transaksiyaların "ac qalmasına" gətirib çıxara bilər.
Bundan qaçmaq üçün sorğularını analiz et, müxtəlif isolation səviyyələrində performansı test et və uyğun indekslərdən istifadə et.
GO TO FULL VERSION