6.9-bob: Normalizatsiya (1NF–3NF), tranzaksiyalar (ACID), izolyatsiya darajalari
6-QISM — Ma'lumotlar bazasi (Database) · 9-mavzu
1. Kirish va motivatsiya
SQL'ni amaliy va ekspert darajada (6.4–6.8) o'rgandik. Endi relatsion DB'ning ilmiy/nazariy asoslariga — DB dizaynining poydevoriga — o'tamiz: normalizatsiya (ma'lumotni to'g'ri tashkil qilish) va tranzaksiyalar (ACID) + izolyatsiya darajalari (parallel ishlashda yaxlitlik). Bu mavzu — "DB'ni shunchaki ishlataman" bilan "DB'ni to'g'ri loyihalayman" o'rtasidagi farq. Intervyularda ham, real loyihada ham — eng muhim bilimlardan.
Normalizatsiya — ma'lumotni jadvallarga to'g'ri bo'lish qoidalari (1NF, 2NF, 3NF). Maqsad — takrorni yo'qotish va anomaliyalarni (yangilash/o'chirish/qo'shish muammolari) oldini olish. Noto'g'ri loyihalangan DB — ma'lumot takrorlanadi, bir joyda yangilanib boshqasida qolib ketadi (nomuvofiqlik), va keyinroq tuzatish — qiyin/qimmat. Normalizatsiya — bu muammolarni boshidanoq oldini oladi.
Tranzaksiya va izolyatsiya — bir nechta foydalanuvchi/so'rov bir vaqtda DB'ni o'zgartirganda yaxlitlikni saqlash. 6.1 2.11-bob da ACID'ni qisqacha ko'rdik; 6.5/6.6 da tranzaksiyani ishlatdik. Endi chuqur: ACID'ning har harfi, izolyatsiya darajalari (parallel anomaliyalar — dirty read, phantom), va qaysisini qachon tanlash. Bank, to'lov, buyurtma — bularsiz xato (pul yo'qolishi, ikki marta sotish) muqarrar.
O'xshatish 1 (normalizatsiya): ma'lumotni takrorlash — har xonada alohida telefon kitobi (raqam o'zgarsa, hammasini yangilash kerak — biri qolib ketadi). Normalizatsiya — bitta markaziy telefon kitobi + har xonada unga ishora (raqam bir joyda; o'zgarsa, bir joyda). Takror yo'q, nomuvofiqlik yo'q.
O'xshatish 2 (izolyatsiya): ikki kassir bir vaqtda oxirgi bitta mahsulotni sotmoqchi. Izolyatsiyasiz — ikkalasi ham "bor" deb ko'radi, ikkalasi ham sotadi (xato — bitta mahsulot ikki marta!). Izolyatsiya — "navbat"/"qulf" bilan buni oldini oladi (biri sotsa, ikkinchisi "tugadi" ko'radi).
Nega muhim?
- DB dizayni poydevori — normalizatsiya to'g'ri loyihalashning asosi.
- Yaxlitlik — ACID/izolyatsiya bank/to'lovda hayotiy (xato qimmat).
- Parallel muammolar — race condition, dirty read — real va xavfli.
- Intervyu/ekspertlik — bu nazariya backend dasturchining majburiy bilimi.
2. Nazariya — chuqur tushuntirish
2.1. Nega normalizatsiya (takror muammolari)
Normalizatsiyasiz (bitta katta jadval) muammolar:
Yomon dizayn (bitta jadval — takror):
| buyurtma | mijoz_ism | mijoz_tel | mahsulot | narx |
| 1 | Ali | +998901112233| Olma | 12000 |
| 2 | Ali | +998901112233| Banan | 18000 | Ali ma'lumoti TAKROR
Anomaliyalar:
Update anomaliyasi: Ali tel o'zgarsa HAR qatorni yangilash (biri qolsa — nomuvofiq)
Delete anomaliyasi: oxirgi buyurtma o'chsa Ali ma'lumoti ham yo'qoladi
Insert anomaliyasi: buyurtmasiz mijoz qo'shib bo'lmaydi (buyurtma kerak)Normalizatsiya — bu anomaliyalarni takrorni yo'qotib hal qiladi (ma'lumotni bo'lib, bog'lab — 6.1: 2.10). Har fakt — bir joyda. Bu — relatsion dizaynning asosiy maqsadi.
2.2. Funksional bog'liqlik (functional dependency)
Normalizatsiya funksional bog'liqlikka asoslanadi: bir ustun boshqasini aniqlaydi:
user_id ism, email (user_id ni bilsangiz, ism/email aniq)
X Y "X Y ni aniqlaydi" (X o'zgarsa, Y aniq)
Maqsad: har ustun PRIMARY KEY'ga to'liq bog'liq bo'lsin (boshqasiga emas)Bu — normalizatsiyaning matematik asosi. "Bu ustun nimaga bog'liq?" — agar PK'ga emas, boshqa ustunga bog'liq bo'lsa — muammo (2NF/3NF buziladi). Hozircha amaliy qoidalarni ko'ramiz.
2.3. 1NF (Birinchi normal forma) — atomik qiymatlar
1NF: har katak atomik (bo'linmas) qiymat; takrorlanuvchi guruh yo'q:
1NF buzilgan (bir katakda ko'p qiymat):
| id | ism | telefonlar |
| 1 | Ali | +99890111, +99890222 | bir katakda ikkita (atomik emas!)
1NF (atomik):
users: | id | ism | phones: | user_id | raqam |
| 1 | Ali | | 1 | +99890111 |
| 1 | +99890222 |1NF qoidasi: bir katak — bitta qiymat (vergul bilan ro'yxat emas, massiv emas). Takrorlanuvchi ustunlar (telefon1, telefon2, telefon3) ham — 1NF buzilishi. Yechim: alohida jadval (one-to-many — 6.1).
2.4. 2NF (Ikkinchi normal forma) — to'liq bog'liqlik
2NF: 1NF + har ustun butun primary keyga bog'liq (qisman emas — digitalocean):
Faqat COMPOSITE PK (ko'p ustunli PK) bo'lganda dolzarb.
2NF buzilgan (PK = order_id + product_id):
| order_id | product_id | miqdor | mahsulot_nomi |
mahsulot_nomi faqat product_id'ga bog'liq (butun PK'ga emas — qisman!)
2NF (qisman bog'liqlikni ajratish):
order_items: | order_id | product_id | miqdor |
products: | product_id | mahsulot_nomi | alohida2NF qoidasi: agar PK bir necha ustundan iborat bo'lsa (composite), har ustun butun PK'ga bog'liq bo'lishi kerak (faqat bir qismiga emas).
mahsulot_nomifaqatproduct_idga bog'liq — uni alohida jadvalga. Yagona ustunli PK'da 2NF avtomatik (qisman bog'liqlik bo'lolmaydi).
2.5. 3NF (Uchinchi normal forma) — tranzitiv bog'liqlik yo'q
3NF: 2NF + tranzitiv bog'liqlik yo'q (ustun boshqa PK bo'lmagan ustunga bog'liq emas — freecodecamp):
3NF buzilgan (tranzitiv):
| user_id | ism | shahar_id | shahar_nomi | shahar_aholisi |
shahar_nomi/aholisi shahar_id'ga bog'liq (user_id'ga EMAS — tranzitiv!)
user_id shahar_id shahar_nomi (zanjir)
3NF (tranzitivni ajratish):
users: | user_id | ism | shahar_id |
cities: | shahar_id | shahar_nomi | shahar_aholisi | alohida3NF qoidasi: PK bo'lmagan ustun boshqa PK bo'lmagan ustunga bog'liq bo'lmasin.
shahar_nomi—user_idga emas,shahar_idga bog'liq (tranzitiv zanjir). Uni alohida jadvalga. 3NF — amaliy standart (ko'p loyiha 3NF'da to'xtaydi).
2.6. BCNF va undan yuqori (qisqacha)
BCNF (Boyce-Codd) — 3NF'ning kuchliroq versiyasi (kam holatlarda kerak)
4NF, 5NF — juda maxsus (ko'p qiymatli bog'liqlik — kamdan-kam)
Amaliyotda: 3NF (yoki BCNF) YETARLI. Undan yuqori — kamdan-kam.Amaliy maslahat: 3NF'gacha normalizatsiya qiling — bu standart. BCNF/4NF/5NF — nazariy, maxsus holatlar (akademik). Ko'p real loyiha 3NF'da.
2.7. Denormalizatsiya (ataylab takror — qachon)
Normalizatsiya har doim eng yaxshi emas. Ba'zan ataylab denormalizatsiya (takror) — tezlik uchun (6.1: 2.10):
Normalizatsiya: takror yo'q, lekin ko'p JOIN 6.7-bob — sekinroq o'qish
Denormalizatsiya: takror bor, lekin JOIN kam — tez o'qish
Qachon denormalizatsiya:
O'qish juda ko'p, yozish kam (hisobot, dashboard)
JOIN juda qimmat (ko'p jadval, katta ma'lumot)
Hisoblangan qiymat (buyurtma_soni — trigger bilan — 6.8: Misol 7)Balans: boshlang'ich — normalizatsiya (3NF — toza, ishonchli). Tezlik muammosi paydo bo'lsa — tanlab denormalizatsiya (o'lchab, kerakli joyda). "Premature denormalization" (vaqtidan oldin) — yomon. MongoDB — denormalizatsiyaga moyil (6.3: embed); SQL — normalizatsiyaga.
2.8. Tranzaksiya nima (takrorlash — 6.1: 2.11)
Tranzaksiya — bir nechta amalni bitta bo'linmas birlik sifatida bajarish:
BEGIN; -- boshlash
UPDATE accounts SET balans = balans - 100 WHERE id = 1;
UPDATE accounts SET balans = balans + 100 WHERE id = 2;
COMMIT; -- hammasi saqla (yoki ROLLBACK bekor)Tranzaksiya — "hammasi yoki hech narsa" (6.5: 2.9, 6.6: 2.12 da ishlatdik). Pul o'tkazish — ikkala UPDATE yoki hech biri. Bu — ACIDning amaliy ko'rinishi.
2.9. ACID — har harf chuqur
A — Atomicity (atomiklik):
tranzaksiya bo'linmas — HAMMASI yoki HECH NARSA (yarim bajarilmaydi)
pul yechildi, lekin qo'shilmadi ROLLBACK (ikkalasi bekor)
C — Consistency (izchillik):
tranzaksiya DB'ni bir TO'G'RI holatdan boshqa TO'G'RI holatga o'tkazadi
(constraint, FK, CHECK — 6.4 — buzilmaydi)
I — Isolation (izolyatsiya):
parallel tranzaksiyalar bir-biriga XALAQIT bermaydi 2.11-bob
(ikki kassir muammosi — o'xshatish 2)
D — Durability (doimiylik):
COMMIT bo'lgan ma'lumot YO'QOLMAYDI (server o'chsa ham — diskda)ACID — relatsion DB'ning kafolati (6.1: 2.11). Eng murakkabi — Isolation (parallel ishlash — 2.10-2.14). Atomicity/Durability — DB avtomatik; Consistency — constraint'lar bilan; Isolation — daraja tanlash bilan.
2.10. Parallel muammolar (read phenomena)
Ko'p tranzaksiya bir vaqtda ishlaganda muammolar (anomaliyalar):
Dirty read (iflos o'qish):
T1 o'zgartirdi (hali COMMIT qilmagan) T2 shu o'zgarishni o'qidi
T1 ROLLBACK qildi T2 mavjud bo'lmagan ma'lumotni o'qidi (xato!)
Non-repeatable read (takrorlanmas o'qish):
T1 qatorni o'qidi T2 uni o'zgartirib COMMIT qildi
T1 yana o'qidi BOSHQA qiymat (bir tranzaksiyada ikki xil natija)
Phantom read (arvoh o'qish):
T1 "yosh>18" so'rovini bajardi (10 qator) T2 yangi qator qo'shdi
T1 yana bajardi 11 qator (yangi "arvoh" qator paydo bo'ldi)
Lost update (yo'qolgan yangilanish):
T1 va T2 bir qatorni o'qidi ikkalasi o'zgartirib yozdi biri yo'qoldiBu anomaliyalar — real va xavfli (5.1: race condition, 5.18: OTP). Izolyatsiya darajasi — qaysi anomaliyalardan himoya qilishni belgilaydi (yuqori daraja = ko'proq himoya, lekin sekinroq — 2.11).
2.11. Izolyatsiya darajalari (4 ta)
SQL standarti 4 izolyatsiya darajasini belgilaydi (past yuqori himoya):
┌─────────────────┬───────────┬──────────────────┬──────────┐
│ Daraja │ Dirty read│ Non-repeatable │ Phantom │
├─────────────────┼───────────┼──────────────────┼──────────┤
│ READ UNCOMMITTED│ mumkin │ mumkin │ mumkin│
│ READ COMMITTED │ yo'q │ mumkin │ mumkin│ default (PostgreSQL)
│ REPEATABLE READ │ yo'q │ yo'q │ /* │ default (MySQL)
│ SERIALIZABLE │ yo'q │ yo'q │ yo'q │ eng kuchli
└─────────────────┴───────────┴──────────────────┴──────────┘
*PostgreSQL REPEATABLE READ phantom'ni ham oldini oladiBalans: yuqori daraja = ko'proq himoya, lekin sekinroq (ko'proq qulf/tekshiruv). READ COMMITTED (PostgreSQL default) — ko'p ilova uchun yetarli. SERIALIZABLE — eng xavfsiz (tranzaksiyalar ketma-ket bo'lgandek), lekin sekin (bank, kritik). Kerakli darajani tanlang.
2.12. Izolyatsiya darajasini sozlash
-- Tranzaksiya uchun daraja
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- ... amallar ...
COMMIT;
-- yoki sessiya darajasida
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;Ko'p loyihada default (READ COMMITTED) yetadi. Kritik amal (pul, zaxira) — yuqoriroq (REPEATABLE READ/SERIALIZABLE). Lekin yuqori daraja — serialization xatosi (konflikt) berishi mumkin tranzaksiyani qayta urinish kerak 2.14-bob.
2.13. Lock (qulf) — pessimistik vs optimistik
Parallel muammolarni hal qilishning ikki yondashuvi:
PESSIMISTIK lock (qulflash):
"Men o'zgartiraman, boshqalar kutsin" qatorni QULFLAYDI
SELECT ... FOR UPDATE; -- qatorni qulflab o'qish (boshqalar kutadi)
Konflikt yo'q; sekin (kutish), deadlock xavfi
OPTIMISTIK lock (versiya):
"O'zgartiraman, lekin yozishda tekshiraman" version ustuni
UPDATE ... WHERE id = 1 AND version = 5; -- version o'zgargan bo'lsa, yangilamaydi
Tez (qulf yo'q); konflikt bo'lsa, qayta urinishPessimistik (FOR UPDATE) — kam konflikt, qisqa tranzaksiya (zaxira kamaytirish). Optimistik (version) — ko'p o'qish, kam konflikt (ko'p foydalanuvchi profil tahrirlaydi). Tanlov — konflikt ehtimoliga qarab.
MVCC (Multi-Version Concurrency Control): PostgreSQL (va MySQL InnoDB) qulfning o'rniga ko'pincha shu mexanizmni ishlatadi — har tranzaksiya ma'lumotning o'z snapshotini (bir lahzadagi versiyasini) ko'radi. UPDATE eski qatorni o'chirmaydi, balki yangi versiya yozadi; eski o'qigan tranzaksiya hali ham eski versiyani ko'radi. Natijada o'quvchilar yozuvchilarni, yozuvchilar o'quvchilarni bloklamaydi — shuning uchun
SELECTodatda qulf kutmaydi. REPEATABLE READ 2.11-bob shu snapshot ustiga quriladi. Kamchiligi — eski versiyalarni tozalash kerak (PostgreSQL'daVACUUM).
2.14. Deadlock va qayta urinish
Deadlock — ikki tranzaksiya bir-birini kutib qoladi (T1 A'ni qulfladi, B'ni kutadi; T2 B'ni qulfladi, A'ni kutadi):
T1: lock A B kutadi
T2: lock B A kutadi
ikkalasi bir-birini kutadi (deadlock!)
DB buni ANIQLAYDI va birini bekor qiladi (deadlock victim)
ilova shu tranzaksiyani QAYTA urinishi kerakYechim: (1) qulflarni bir tartibda olish (A, keyin B — har doim); (2) tranzaksiyani qisqa tutish; (3) deadlock/serialization xatosida qayta urinish (retry — 5.22 ruhida). Bank/yuqori yukli tizimda muhim.
2.15. Node.js'da tranzaksiya + retry
// Tranzaksiya + serialization xatosida qayta urinish (2.12, 2.14)
async function tranzaksiyaRetry(fn, urinish = 3) {
for (let i = 0; i < urinish; i++) {
const client = await pool.connect();
try {
await client.query("BEGIN ISOLATION LEVEL SERIALIZABLE");
const natija = await fn(client);
await client.query("COMMIT");
return natija;
} catch (err) {
await client.query("ROLLBACK");
if (err.code === "40001" && i < urinish - 1) continue; // serialization_failure retry
throw err;
} finally {
client.release(); // (6.5: 2.10)
}
}
}Yuqori izolyatsiya (SERIALIZABLE) — konflikt (40001) berishi mumkin qayta urinish (idempotent — 5.22: 2.13). Bu — kritik tizimlarda standart naqsh.
2.16. Best practices (14)
3NF'gacha normalizatsiya (toza dizayn — 2.5); tanlab denormalizatsiya (o'lchab — 2.7)
Tranzaksiya muhim amalda (pul, zaxira — atomik — 2.8)
Tranzaksiyani QISQA tuting (uzun lock, deadlock — 2.14)
To'g'ri izolyatsiya darajasi (default odatda yetadi; kritik — yuqori — 2.11)
Deadlock/serialization qayta urinish (2.14, 2.15)
FOR UPDATE (pessimistik) yoki version (optimistik) — konfliktga qarab 2.13-bob
Constraint'lar (consistency — FK/CHECK — 6.4) bilan yaxlitlik3. Sintaksis / qoidalar — tez ma'lumotnoma
NORMALIZATSIYA:
1NF — atomik qiymat (bir katak, bir qiymat — 2.3)
2NF — 1NF + butun PK'ga bog'liqlik (qisman emas — 2.4)
3NF — 2NF + tranzitiv bog'liqlik yo'q 2.5-bob
ACID 2.9-bob: Atomicity, Consistency, Isolation, Durability
IZOLYATSIYA 2.11-bob: READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLEBEGIN [ISOLATION LEVEL ...]; ... COMMIT/ROLLBACK; -- tranzaksiya (2.8, 2.12)
SELECT ... FOR UPDATE; -- pessimistik lock (2.13)
UPDATE ... WHERE id=? AND version=?; -- optimistik (2.13)4. Batafsil misollar
Misol 1 — Normalizatsiya bosqichlari (2.3-2.5)
Boshlang'ich (normalizatsiyasiz — 2.1):
| buyurtma_id | mijoz | tel | mahsulotlar | shahar | shahar_kod |
| 1 | Ali | +99890111 | Olma, Banan | Toshkent | 100 |
1NF (atomik — mahsulotlarni ajrating — 2.3):
order_items: | buyurtma_id | mahsulot |
| 1 | Olma |
| 1 | Banan |
2NF (qisman bog'liqlikni ajrating — 2.4):
(composite PK bo'lsa — mahsulot tafsilotini alohida)
3NF (tranzitivni ajrating — shahar — 2.5):
orders: | id | mijoz_id | cities: | id | shahar | kod |
users: | id | ism | tel | shahar_id |
har fakt bir joyda (takror yo'q)Misol 2 — 3NF schema (toza dizayn — 2.5)
-- 3NF'ga mos schema (har jadval — bir mavzu, takror yo'q)
CREATE TABLE cities (
id SERIAL PRIMARY KEY, nom VARCHAR(50), kod VARCHAR(10)
);
CREATE TABLE users (
id SERIAL PRIMARY KEY, ism VARCHAR(50), tel VARCHAR(20),
city_id INTEGER REFERENCES cities(id) -- shaharga ishora (3NF — 2.5)
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), created_at TIMESTAMPTZ
);
CREATE TABLE order_items (
order_id INTEGER REFERENCES orders(id),
product_id INTEGER REFERENCES products(id),
miqdor INTEGER, narx DECIMAL(10,2), -- narx — snapshot (6.3: Misol 7)
PRIMARY KEY (order_id, product_id) -- composite PK
);
-- Har fakt bir joyda; bog'lanish FK bilan (6.4: 2.6)Misol 3 — Tranzaksiya (pul o'tkazish — atomik — 2.8, 2.9)
// Atomik pul o'tkazish (6.6: 2.12 ga o'xshash)
export async function pulOtkaz(fromId, toId, summa) {
const client = await pool.connect();
try {
await client.query("BEGIN"); // tranzaksiya (2.8)
// Atomic: yechish (balans yetarli bo'lsa)
const { rowCount } = await client.query(
"UPDATE accounts SET balans = balans - $1 WHERE id = $2 AND balans >= $1",
[summa, fromId]
);
if (rowCount === 0) throw new Error("Balans yetarli emas"); // ROLLBACK
await client.query("UPDATE accounts SET balans = balans + $1 WHERE id = $2", [summa, toId]);
await client.query("INSERT INTO transfers (from_id, to_id, summa) VALUES ($1,$2,$3)",
[fromId, toId, summa]);
await client.query("COMMIT"); // hammasi saqla (Atomicity — 2.9)
} catch (err) {
await client.query("ROLLBACK"); // xato BEKOR (yarim o'tkazish yo'q)
throw err;
} finally {
client.release(); // (6.5: 2.10)
}
}Misol 4 — Pessimistik lock (zaxira — 2.13)
// Mahsulot zaxirasini xavfsiz kamaytirish (race condition'siz — 2.10, 2.13)
export async function zaxiraKamaytir(productId, miqdor) {
const client = await pool.connect();
try {
await client.query("BEGIN");
// FOR UPDATE — qatorni QULFLAB o'qish (boshqa tranzaksiyalar kutadi — 2.13)
const { rows } = await client.query(
"SELECT zaxira FROM products WHERE id = $1 FOR UPDATE", [productId]
);
if (rows[0].zaxira < miqdor) throw new Error("Zaxira yetarli emas");
await client.query("UPDATE products SET zaxira = zaxira - $1 WHERE id = $2",
[miqdor, productId]);
await client.query("COMMIT");
} catch (err) {
await client.query("ROLLBACK");
throw err;
} finally {
client.release();
}
}
// FOR UPDATE'siz: ikki so'rov bir vaqtda "zaxira bor" deb ko'rib, ikkalasi sotardi (xato — 2.10)Misol 5 — Optimistik lock (version — 2.13)
// Optimistik lock (version ustuni — 2.13)
// users jadvalida: version INTEGER DEFAULT 0
export async function profilYangila(id, data, version) {
const { rowCount } = await pool.query(
`UPDATE users SET ism = $1, version = version + 1
WHERE id = $2 AND version = $3`, // version mos bo'lsa (2.13)
[data.ism, id, version]
);
if (rowCount === 0) {
throw new Error("Ma'lumot boshqa joyda o'zgargan — qayta yuklang"); // konflikt
}
}
// Ikki foydalanuvchi bir profilni tahrirlasa, ikkinchisining version eskirgan konfliktMisol 6 — Izolyatsiya + retry (kritik — 2.15)
// SERIALIZABLE + qayta urinish (eng xavfsiz, kritik amal — 2.15)
export async function kritikAmal(fn) {
for (let i = 0; i < 3; i++) {
const client = await pool.connect();
try {
await client.query("BEGIN ISOLATION LEVEL SERIALIZABLE"); // eng kuchli (2.11)
const natija = await fn(client);
await client.query("COMMIT");
return natija;
} catch (err) {
await client.query("ROLLBACK");
if (err.code === "40001" && i < 2) { // serialization konflikti
await new Promise(r => setTimeout(r, 50 * (i + 1))); // kichik kutish
continue; // qayta urin (2.14)
}
throw err;
} finally {
client.release();
}
}
}5. To'g'ri va noto'g'ri holatlar
1) Takrorli (normalizatsiyasiz) dizayn
bitta katta jadval, ma'lumot takror (anomaliyalar — 2.1)
3NF — har fakt bir joyda, FK bilan bog'langan (2.5)2) Bir katakda ko'p qiymat (1NF buzilishi)
-- telefonlar VARCHAR "raqam1, raqam2" (atomik emas — 2.3)
-- alohida phones jadvali (one-to-many)3) Tranzaksiyasiz pul o'tkazish
// ikki alohida UPDATE (orasida xato yarim o'tkazish — 2.8)
await q("UPDATE ... balans - 100"); await q("UPDATE ... balans + 100");
// tranzaksiya (atomik)
BEGIN; ...; COMMIT;4) Race condition (lock'siz zaxira)
// o'qib, keyin yangilash (orasida boshqa so'rov — 2.10)
const z = await q("SELECT zaxira ..."); if (z > 0) await q("UPDATE zaxira - 1");
// FOR UPDATE yoki atomik UPDATE WHERE zaxira >= miqdor (2.13)5) Uzun tranzaksiya
tranzaksiya ichida sekin ish (tashqi API, kutish) lock uzoq, deadlock (2.14)
tranzaksiyani qisqa tuting (faqat DB amallari)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Ma'lumot nomuvofiq (bir joyda yangilangan, boshqada eski)
Sababi: takror (normalizatsiyasiz — 2.1). Yechimi: 3NF; ma'lumot bir joyda; FK.
Xato 2 — deadlock detected (40P01)
Sababi: ikki tranzaksiya bir-birini kutadi 2.14-bob. Yechimi: qulflarni bir tartibda; qisqa tranzaksiya; qayta urinish.
Xato 3 — could not serialize access (40001)
Sababi: SERIALIZABLE konflikti 2.12-bob. Yechimi: qayta urinish (Misol 6, 2.15).
Xato 4 — Yo'qolgan yangilanish (lost update)
Sababi: ikki tranzaksiya bir qatorni yozdi 2.10-bob. Yechimi: FOR UPDATE (pessimistik) yoki version (optimistik — 2.13).
Xato 5 — Juda normalizatsiya (ko'p JOIN, sekin)
Sababi: o'qish ko'p, JOIN qimmat 2.7-bob. Yechimi: tanlab denormalizatsiya; materialized view 6.8-bob; kesh 5.21-bob.
Xato 6 — Tranzaksiya ROLLBACK qilinmadi (xatoda)
Sababi: catch'da ROLLBACK yo'q. Yechimi: try/catch/finally; xatoda ROLLBACK, doim release.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- DB asoslari 6.1-bob: ACID, relatsion model.
- SQL/JOIN (6.4, 6.7): normalizatsiya — JOIN sababi.
- Tranzaksiya (6.5, 6.6): ishlatish; bu yerda chuqur.
- Race condition 5.1-bob: parallel muammolar.
- Redis 5.21-bob: denormalizatsiya muqobili (kesh).
- Trigger 6.8-bob: denormalizatsiya maydonini saqlash.
- Query optimization 6.10-bob: denormalizatsiya/indeks.
- ER modeling 6.17-bob: normalizatsiya — dizayn.
- Idempotentlik 5.22-bob: retry bilan.
- Xavfsizlik (14): yaxlitlik (pul).
8. Eng yaxshi amaliyotlar (best practices)
- 3NF'gacha normalizatsiya (toza, anomaliyasiz — 2.5); tanlab denormalizatsiya (o'lchab — 2.7).
- 1NF: atomik qiymat (massiv/ro'yxat katakda emas — 2.3).
- Tranzaksiya muhim amalda (pul/zaxira — atomik — 2.8).
- Tranzaksiyani qisqa tuting (lock/deadlock — 2.14).
- To'g'ri izolyatsiya (default odatda yetadi; kritik — yuqori — 2.11).
- Race condition: FOR UPDATE yoki version (konfliktga qarab — 2.13).
- Deadlock/serialization qayta urinish (2.14, 2.15).
- Constraint'lar bilan consistency (FK/CHECK — 6.4, 2.9).
- try/catch/finally (ROLLBACK + release — Xato 6).
- Snapshot (buyurtma narxi — denormalizatsiya — 6.3: Misol 7).
9. Amaliy loyiha: "Normalizatsiyalangan, Tranzaksiyali DB"
DB dizayni va yaxlitlikni mustahkamlash.
Maqsad
3NF schema loyihalash va kritik amallarni tranzaksiya + lock bilan xavfsiz qilish (e-commerce — buyurtma, zaxira, to'lov).
Talablar (requirements)
- Normalizatsiya: takrorli dizayndan boshlab, 1NF2NF3NF'ga keltiring (Misol 1, 2.3-2.5).
- 3NF schema: users/cities/orders/order_items/products — FK, takror yo'q (Misol 2).
- Tranzaksiya: pul o'tkazish yoki buyurtma (atomik — Misol 3, 2.8).
- Pessimistik lock: zaxira kamaytirish (FOR UPDATE — Misol 4, 2.13).
- Optimistik lock: profil tahrirlash (version — Misol 5, 2.13).
- Izolyatsiya + retry: kritik amal (SERIALIZABLE + qayta urinish — Misol 6, 2.15).
- Race condition test: lock'siz vs lock bilan farqni ko'rsating 2.10-bob.
- Denormalizatsiya tahlili: qaysi joyda kerak — asoslang 2.7-bob.
- Deadlock oldini olish: qulf tartibi, qisqa tranzaksiya 2.14-bob.
Maslahatlar (hint)
- 1NF: atomik (massiv yo'q); 3NF: tranzitiv yo'q (2.3, 2.5).
- Tranzaksiya: BEGIN/COMMIT/ROLLBACK + finally release (Misol 3, 6-xato).
- Zaxira: FOR UPDATE yoki UPDATE WHERE zaxira >= miqdor (2.13, 4-holat).
- Optimistik: version ustuni (Misol 5).
- SERIALIZABLE: 40001 retry (Misol 6).
- Tranzaksiya qisqa (deadlock — 2.14).
"Tayyor" mezonlari (acceptance criteria)
- Normalizatsiya bosqichlari (1NF3NF) ko'rsatilgan.
- 3NF schema (FK, takror yo'q).
- Tranzaksiya (atomik, ROLLBACK).
- Pessimistik lock (FOR UPDATE) zaxirada.
- Optimistik lock (version) tahrirlashda.
- Izolyatsiya + retry (kritik).
- Race condition farqi ko'rsatilgan.
- Denormalizatsiya qarori asoslangan.
- Deadlock oldini olish.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda DB dizayni va yaxlitlik asoslarini chuqur o'rgandik:
- Normalizatsiya (takror/anomaliyalarni yo'qotish — 2.1): 1NF (atomik — 2.3), 2NF (to'liq bog'liqlik — 2.4), 3NF (tranzitiv yo'q — 2.5); denormalizatsiya (tanlab, tezlik — 2.7).
- Tranzaksiya (atomik birlik — 2.8); ACID (har harf — 2.9).
- Parallel muammolar (dirty/non-repeatable/phantom read, lost update — 2.10); izolyatsiya darajalari (4 ta — 2.11, 2.12).
- Lock (pessimistik FOR UPDATE vs optimistik version — 2.13); deadlock + retry (2.14, 2.15).
Keyingi bob — 6.10-bob: Indekslar va query optimization, EXPLAIN. Toza dizayn (normalizatsiya) va yaxlitlik (ACID)ni bildik; endi tezlikka o'tamiz. Indekslar (chuqur — B-tree, composite, covering, partial), so'rovlarni optimallashtirish, va EXPLAIN (so'rov rejasini ko'rish — sekin so'rovni topish va tuzatish). Bu — production'da DB tezligining kaliti.
Foydalanilgan rasmiy/ishonchli manbalar
- DigitalOcean / freeCodeCamp — Database Normalization (1NF, 2NF, 3NF, BCNF)
- PostgreSQL docs — Transaction Isolation; AWS — ACID; izolyatsiya darajalari va anomaliyalar
- PostgreSQL docs — Explicit Locking (FOR UPDATE), serialization failure
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!