Isolation Levels — READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE
Muammodan boshlaylik
Ikki tranzaksiya bir vaqtda ishlayapti:
- A — buxgalter oylik hisobotni tuzyapti: 50 ta
SELECT, 2 daqiqa davom etadi - B — shu paytda mijozlar buyurtma berib, narxlar yangilanmoqda
Savol: A tranzaksiyasi B ning o'zgarishlarini ko'rishi kerakmi? Agar ko'rsa — hisobotning boshi va oxiri turli holatdagi ma'lumotga asoslanadi: jami summa qatorlar yig'indisiga teng chiqmaydi. Agar ko'rmasa — qanday qilib?
Isolation darajasi — tranzaksiyalar bir-birining o'zgarishlarini qanchalik "ko'rishi" ni belgilaydi. Bu tezlik va aniqlik o'rtasidagi tanlov.
Uch xil anomaliya
Isolation yetarli bo'lmaganda paydo bo'ladigan muammolar.
1. Dirty read — "iflos" o'qish
Boshqa tranzaksiyaning hali COMMIT qilinmagan o'zgarishini o'qish:
B: START TRANSACTION
B: UPDATE mahsulotlar SET narx = 100 WHERE id = 1
A: SELECT narx FROM mahsulotlar WHERE id = 1 → 100 ⚠️
B: ROLLBACK (narx yana 12 500 000)
A: (100 so'mlik narx bilan buyurtma yaratdi — hech qachon mavjud bo'lmagan qiymat)
2. Non-repeatable read — takrorlanmaydigan o'qish
Bir tranzaksiya ichida bir xil qatorni ikki marta o'qib, turli natija olish:
A: START TRANSACTION
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 4
B: UPDATE mahsulotlar SET soni = 0 WHERE id = 1; COMMIT
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 0 ⚠️ — o'sha tranzaksiyada!
3. Phantom read — "arvoh" qatorlar
Bir xil shart bilan ikki marta so'rab, turli qatorlar to'plamini olish:
A: SELECT COUNT(*) FROM buyurtmalar WHERE holat = 'yangi' → 10
B: INSERT INTO buyurtmalar (holat) VALUES ('yangi'); COMMIT
A: SELECT * FROM buyurtmalar WHERE holat = 'yangi' → 11 qator ⚠️
Hisobotda: "jami 10 ta", lekin ro'yxatda 11 ta.
To'rt daraja
| Daraja | Dirty read | Non-repeatable | Phantom | Tezlik |
|---|---|---|---|---|
READ UNCOMMITTED |
⚠️ Bor | ⚠️ Bor | ⚠️ Bor | Eng tez |
READ COMMITTED |
✅ Yo'q | ⚠️ Bor | ⚠️ Bor | Tez |
REPEATABLE READ (MySQL standarti) |
✅ Yo'q | ✅ Yo'q | ✅ Deyarli yo'q* | O'rtacha |
SERIALIZABLE |
✅ Yo'q | ✅ Yo'q | ✅ Yo'q | Eng sekin |
* InnoDB ning REPEATABLE READ i oddiy SELECT lar uchun phantom larni ham oldini oladi (pastda).
Darajani ko'rish va o'zgartirish
SELECT @@transaction_isolation; -- REPEATABLE-READ
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -- shu ulanish uchun
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- faqat keyingi tranzaksiya
READ UNCOMMITTED
Boshqalarning commit qilinmagan o'zgarishlari ko'rinadi. Deyarli hech qachon ishlatilmaydi — faqat juda taxminiy statistika uchun (masalan, "taxminan nechta qator") va aniqlik umuman muhim bo'lmaganda.
READ COMMITTED
Har bir SELECT — o'sha lahzadagi commit qilingan ma'lumotni ko'radi. Tranzaksiya davomida natijalar o'zgarishi mumkin.
PostgreSQL, Oracle, SQL Server ning standart darajasi. Ko'p veb-ilovalar uchun yetarli: har bir so'rov eng yangi ma'lumotni oladi.
REPEATABLE READ — MySQL standarti
Tranzaksiyadagi birinchi SELECT paytida ma'lumotning "suratga olinishi" (snapshot) yaratiladi. Tranzaksiya oxirigacha barcha SELECT lar shu suratni ko'radi — boshqalar nima commit qilishidan qat'i nazar.
A: START TRANSACTION
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 4 (surat olindi)
B: UPDATE mahsulotlar SET soni = 0 WHERE id = 1; COMMIT
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 4 ✅ (surat)
A: COMMIT
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 0 (yangi tranzaksiya — yangi surat)
Buxgalterning hisoboti uchun ideal: 2 daqiqa davomida u bir xil, izchil ma'lumotni ko'radi.
MVCC — qanday ishlaydi
InnoDB eski ma'lumotni darhol ustidan yozmaydi. Qator o'zgarganda eski versiyasi undo log da saqlanadi. Har bir tranzaksiya o'zining surati vaqtiga mos versiyani o'qiydi.
Bu MVCC (Multi-Version Concurrency Control). Asosiy foyda: o'quvchilar yozuvchilarni bloklamaydi, yozuvchilar o'quvchilarni bloklamaydi. Hisobot 2 daqiqa o'qiyotganda ham buyurtmalar bemalol yoziladi.
Muhim tuzoq: o'qish va yozish farqi
Surat faqat oddiy SELECT ga taalluqli. UPDATE, DELETE va qulflovchi o'qishlar (SELECT ... FOR UPDATE) doim eng yangi commit qilingan ma'lumot bilan ishlaydi:
A: START TRANSACTION
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 4 (surat)
B: UPDATE mahsulotlar SET soni = 1 WHERE id = 1; COMMIT
A: UPDATE mahsulotlar SET soni = soni - 1 WHERE id = 1
-- haqiqiy qiymat 1 dan ayiradi → 0 (4 dan emas!)
A: SELECT soni FROM mahsulotlar WHERE id = 1 → 0 (o'z o'zgarishini ko'radi)
Shuning uchun "o'qib, ilovada hisoblab, yozish" naqshi xavfli (12-dars):
❌ A: SELECT soni ... → 4 (surat)
A: (ilovada: 4 - 1 = 3)
A: UPDATE ... SET soni = 3 ← B ning o'zgarishi yo'qoldi!
✅ A: UPDATE ... SET soni = soni - 1 WHERE soni >= 1
✅ A: SELECT soni ... FOR UPDATE ← eng yangi qiymat + qulf (38-dars)
SERIALIZABLE
Eng qat'iy daraja: tranzaksiyalar go'yo birin-ketin bajarilgandek natija beradi. InnoDB buning uchun oddiy SELECT larni ham avtomatik SELECT ... FOR SHARE ga aylantiradi — ya'ni o'qilgan qatorlar qulflanadi.
Natija: anomaliyalar umuman yo'q, lekin ko'p kutish va deadlock lar (38-dars). Faqat juda muhim, kam takrorlanadigan amallar uchun.
Qaysi darajani tanlash
| Vaziyat | Daraja |
|---|---|
| Oddiy veb-ilova, CRUD | REPEATABLE READ (standart) yoki READ COMMITTED |
| Uzoq hisobotlar, eksport — izchil surat kerak | REPEATABLE READ |
| Yuqori parallellik, kamroq qulf, eng yangi ma'lumot kerak | READ COMMITTED |
| Moliyaviy hisob-kitob, qat'iy to'g'rilik | Kerakli joyda SELECT ... FOR UPDATE yoki SERIALIZABLE |
| Taxminiy statistika | READ UNCOMMITTED (kamdan-kam) |
Ko'p hollarda darajani o'zgartirish shart emas. Muhimi — xavfli naqshlardan qochish (o'qib-keyin-yozish) va kerakli joyda aniq qulflash (FOR UPDATE).
Nima uchun shunday?
Nima uchun eng xavfsiz daraja (SERIALIZABLE) standart emas?
Chunki xavfsizlikning narxi — parallellik. SERIALIZABLE da hisobot o'qigan har bir qator qulflanadi va shu 2 daqiqa davomida hech kim u qatorlarni o'zgartira olmaydi — sayt "qotib" qoladi. Real tizimlarda bir vaqtda yuzlab tranzaksiya ishlaydi. Har bir baza o'zining "oltin o'rtasini" tanlagan: MySQL — REPEATABLE READ (MVCC tufayli o'quvchilar baribir bloklanmaydi), PostgreSQL — READ COMMITTED. Ikkalasi ham amalda yaxshi ishlaydi, agar dasturchi anomaliyalarni bilsa.
Xulosa
Eslab qoling:
- Uch anomaliya: dirty read, non-repeatable read, phantom read
- To'rt daraja:
READ UNCOMMITTED<READ COMMITTED<REPEATABLE READ<SERIALIZABLE - MySQL standarti —
REPEATABLE READ: tranzaksiya bitta "surat"ni ko'radi - MVCC — o'quvchilar va yozuvchilar bir-birini bloklamaydi
- Surat faqat oddiy
SELECTuchun;UPDATEvaFOR UPDATE— eng yangi ma'lumot bilan - "O'qib, ilovada hisoblab, yozish" — xavfli; atomar
UPDATEyokiFOR UPDATE SET SESSION TRANSACTION ISOLATION LEVEL ...
Keyingi dars
38-dars: Locking — Row lock, Table lock, Deadlock va yechimi