IlmHamroh
JavaScript Full-stack/26-qism. SQL va PostgreSQL7/64-dars16 daqiqa
Mundarija (34)

ACID, BASE, CAP va PACELC: baza qanday kafolat beradi

Qisqacha: ACID — relatsion bazaning tranzaksiya uchun to'rtta va'dasi: hammasi yoki hech narsa (Atomicity), qoidalar buzilmaydi (Consistency), parallel tranzaksiyalar bir-biriga xalaqit bermaydi (Isolation), tasdiqlangan ma'lumot o'chib qolmaydi (Durability). Ma'lumot ko'p serverga bo'lingan tizimlarda bu va'dalarning bir qismidan voz kechiladi. CAP teoremasi aytadiki, tarmoq uzilganda yo aniqlik, yo ishlab turish tanlanadi; PACELC esa uzilish bo'lmaganda ham tezlik va aniqlik orasida tanlov borligini qo'shadi. BASE — "oxir-oqibat mos keladi" falsafasi.

Bu darsda

  • Tranzaksiya nima ekanini va BEGIN/COMMIT/ROLLBACK vazifasini tushuntirasiz.
  • ACID'ning to'rtta harfini PostgreSQL'dagi haqiqiy misollar bilan izohlaysiz.
  • Server "o'ldirilganda" tasdiqlangan ma'lumot nega saqlanib qolishini (WAL) aytasiz.
  • BASE va eventual consistency nima ekanini, qayerda o'rinli ekanini bilasiz.
  • CAP va PACELC'ni afsonalarsiz, sodda misol bilan tushuntira olasiz.

Oldin bilishingiz kerak: DB turlari xaritasi va SQL vs NoSQL, Relatsion model.

1. Nega bu kerak?

Aziz Click orqali Dilnoza'ga 150 000 so'm o'tkazmoqchi. Bazada bu ikki amal: Dilnoza hisobiga qo'shish va Aziz hisobidan ayirish. Birinchisi bajarildi, ikkinchisida xato chiqdi — Aziz'da bunday pul yo'q ekan. Endi nima bo'ladi?

  • Agar birinchi amal saqlanib qolsa — 150 000 so'm havodan paydo bo'ldi.
  • Agar elektr o'chib qolsa va baza "yarim" holatda qolsa — kim qancha pulga egaligini hech kim bilmaydi.
  • Agar shu payt Aziz telefondan yana bir o'tkazma boshlasa — ikkala o'tkazma bir-birini buzishi mumkin.

DB turlari xaritasi va SQL vs NoSQL darsida "relatsion baza kuchli tranzaksiya beradi" degan edik. Endi bu "kuchli" so'zining ichini ochamiz. Bu kafolatlar bo'lmasa, har dasturchi ularni o'z kodida qayta ixtiro qilishi kerak bo'lardi — va ko'pincha xato bilan.

Hayotiy o'xshatish: notarius idorasidagi uy oldi-sotdisi. Hujjat imzolanmaguncha hech narsa o'zgarmaydi. Imzolandi — reyestrga yozildi, ertaga idora yonib ketsa ham yozuv saqlanadi. Bir vaqtda ikki xaridor bitta uyni sotib ololmaydi.

2. Tranzaksiya

2.1 Tranzaksiya nima

Tranzaksiya (transaction) — bitta butun ish sifatida bajariladigan buyruqlar guruhi. Uni IndexedDB va brauzer xotira kvotasi bilan ishlaganda brauzerda ko'rgansiz: bir nechta yozuv — yo hammasi, yo hech biri. Bazada tranzaksiya uchta buyruq bilan boshqariladi:

Buyruq Ma'nosi
BEGIN tranzaksiyani boshlash
COMMIT hammasini tasdiqlash va saqlash
ROLLBACK hammasini bekor qilish

Bu darsdagi SQL natijalarini kanon PostgreSQL 18.6 bazasida olingan haqiqiy chiqishdan ko'chirdik. UPDATE — mavjud qatorni o'zgartirish buyrug'i, uni UPDATE va DELETE xavfsiz darsida o'rganamiz. Hozir uni "shu qatorni o'zgartir" deb o'qing.

2.2 Tajriba uchun jadval

Kanon kichik "hisob" jadvali yaratdi. Balans manfiy bo'lishi mumkin emas — buni CHECK qoidasi kuzatadi:

sql
CREATE TABLE t07_hisob (
  ism    text PRIMARY KEY,
  balans numeric(12,2) NOT NULL CHECK (balans >= 0)
);
INSERT INTO t07_hisob VALUES ('Aziz', 100000), ('Dilnoza', 50000);
text
CREATE TABLE
INSERT 0 2

Aziz'da 100 000, Dilnoza'da 50 000 so'm. numeric(12,2) — aniq o'nlik son (pul uchun to'g'ri tur, PostgreSQL ma'lumot turlari darsida).

3. ACID: to'rtta harf

3.1 A — Atomicity (bo'linmaslik)

Atomicity (bo'linmaslik) — tranzaksiya bo'linmaydi: yo hamma buyrug'i bajariladi, yo hech biri. "Atom" — yunoncha "bo'linmas". «Nega bu kerak?» bo'limidagi voqeani bazada takrorlaymiz — Aziz 150 000 so'm o'tkazmoqchi, lekin uning 100 000 so'mi bor:

sql
BEGIN;
UPDATE t07_hisob SET balans = balans + 150000 WHERE ism = 'Dilnoza';
UPDATE t07_hisob SET balans = balans - 150000 WHERE ism = 'Aziz';
COMMIT;
SELECT * FROM t07_hisob ORDER BY ism;

Natija:

text
BEGIN
UPDATE 1
ERROR:  new row for relation "t07_hisob" violates check constraint "t07_hisob_balans_check"
DETAIL:  Failing row contains (Aziz, -50000.00).
ROLLBACK
   ism   |  balans
---------+-----------
 Aziz    | 100000.00
 Dilnoza |  50000.00
(2 rows)

Qatorma-qator ko'ramiz:

  1. UPDATE 1 — Dilnoza'ga 150 000 qo'shildi (1 qator o'zgardi).
  2. Aziz'dan ayirishda balans -50000 bo'lardi — CHECK buni rad etdi. Tarjimasi: "t07_hisob dagi yangi qator t07_hisob_balans_check cheklovini buzadi".
  3. Biz COMMIT yozdik, lekin psql ROLLBACK deb javob berdi. Xatodan keyingi COMMIT Postgres'da bekor qilishga aylanadi.
  4. Natija: ikkala balans boshidagidek. Dilnoza'ga qo'shilgan 150 000 ham bekor bo'ldi.

Pul havodan paydo bo'lmadi. Buni ilova kodi emas, baza kafolatladi.

3.2 Xatodan keyin tranzaksiya "buzilgan"

Postgres'da yana bir qoida bor: tranzaksiya ichida bitta xato bo'lsa, keyingi buyruqlar ham bajarilmaydi:

sql
BEGIN;
SELECT 1/0;
SELECT * FROM t07_hisob;
ROLLBACK;

Natija:

text
BEGIN
ERROR:  division by zero
ERROR:  current transaction is aborted, commands ignored until end of transaction block
ROLLBACK

Ikkinchi xatoning tarjimasi: "joriy tranzaksiya bekor qilingan, tranzaksiya bloki tugaguncha buyruqlar e'tiborsiz qoldiriladi". Oddiy SELECT ham ishlamadi — chunki u "buzilgan" tranzaksiya ichida. Chiqish yo'li bitta: ROLLBACK. Bu xabarni backend loglarida ko'p uchratasiz: u asl xato emas, asl xato undan oldingi qatorda.

3.3 C — Consistency (izchillik)

Consistency (izchillik) — tranzaksiya bazani bir to'g'ri holatdan boshqa to'g'ri holatga o'tkazadi. "To'g'ri" ni siz belgilaysiz: CHECK, PRIMARY KEY, UNIQUE, tashqi kalit. Baza ularni har buyruqda tekshiradi:

sql
INSERT INTO t07_hisob VALUES ('Aziz', 1);

Natija:

text
ERROR:  duplicate key value violates unique constraint "t07_hisob_pkey"
DETAIL:  Key (ism)=(Aziz) already exists.

Tarjimasi: "takror kalit qiymati t07_hisob_pkey noyoblik cheklovini buzadi. (ism)=(Aziz) kaliti allaqachon bor". Endi muvaffaqiyatli o'tkazma — 30 000 so'm:

sql
BEGIN;
UPDATE t07_hisob SET balans = balans - 30000 WHERE ism = 'Aziz';
UPDATE t07_hisob SET balans = balans + 30000 WHERE ism = 'Dilnoza';
COMMIT;
SELECT *, sum(balans) OVER () AS jami FROM t07_hisob ORDER BY ism;

Natija:

text
BEGIN
UPDATE 1
UPDATE 1
COMMIT
   ism   |  balans  |   jami
---------+----------+-----------
 Aziz    | 70000.00 | 150000.00
 Dilnoza | 80000.00 | 150000.00
(2 rows)

jami ustuni — hamma balanslar yig'indisi (bu yozuv usulini Window funksiyalar 1: ranking darsida o'rganamiz). O'tkazmadan oldin ham, keyin ham 150 000. Pul ko'chdi, lekin yo'qolmadi va paydo bo'lmadi.

Muhim: baza faqat sizga aytilgan qoidalarni kuzatadi. "Jami doim 150 000" qoidasini baza bilmaydi — u to'g'ri yozilgan tranzaksiya tufayli saqlandi. Shu sabab qoidalarni iloji boricha bazaga yozish kerak (CREATE TABLE va cheklovlar).

3.4 I — Isolation (izolyatsiya)

Isolation (izolyatsiya, ya'ni ajratilganlik) — bir vaqtda ishlayotgan tranzaksiyalar bir-birining chala ishini ko'rmaydi. Aziz o'tkazma qilayotganda, hisobot chiqarayotgan boshqa tranzaksiya "Dilnoza'ga qo'shildi, Aziz'dan hali ayirilmadi" holatini ko'rmasligi kerak.

Bu ajratish bir necha darajada bo'ladi — ularni izolyatsiya darajalari (isolation levels) deyiladi. Kuchliroq daraja — xavfsizroq, lekin sekinroq. Postgres'da sukut darajasi — READ COMMITTED: har so'rov faqat tasdiqlangan ma'lumotni ko'radi. Buni ko'rish uchun bir vaqtda ikkita ulanish kerak, shuning uchun uni Read phenomena va izolyatsiya darajalari darsida Node.js bilan sinaymiz.

3.5 D — Durability (mustahkamlik)

Durability (mustahkamlik) — COMMIT javobi kelgan bo'lsa, ma'lumot saqlangan. Server o'chsa, elektr ketsa ham.

Postgres buni WAL (Write-Ahead Log — oldindan yoziladigan jurnal) bilan qiladi. Har o'zgarish avval jurnal fayliga yoziladi va diskka majburan tushiriladi. Jadval fayllari keyinroq yangilanadi. Server qulasa, qayta yonganda jurnalni o'qib, tasdiqlangan hamma narsani tiklaydi.

sequenceDiagram
  participant I as Ilova
  participant P as Postgres
  participant W as WAL (disk)
  I->>P: COMMIT
  P->>W: jurnalga yozish
  W-->>P: diskda
  P-->>I: COMMIT tayyor
  Note over P: qulash
  P->>W: qayta yonganda o'qiydi
  Note over P: tasdiqlanganlar tiklandi

Nimaga qarang: ilova COMMIT javobini jurnal diskka tushgandan keyin oladi. Shuning uchun "javob keldi, lekin ma'lumot yo'qoldi" holati bo'lmaydi.

3.6 Durability tajribasi: serverni "o'ldirish"

Kanon buni haqiqatan sinadi. Bitta tranzaksiya qator qo'shib COMMIT qildi. Boshqa tranzaksiya ham qator qo'shdi, lekin COMMIT qilmadi. Keyin Postgres konteyneri docker kill --signal=KILL bilan to'xtatildi — bu elektrni sug'urib olishga o'xshaydi: dasturga yakunlash uchun hech qanday imkon berilmaydi. Qayta yonganda Postgres logida:

text
LOG:  database system was not properly shut down; automatic recovery in progress
LOG:  redo starts at 0/2999ED0
LOG:  database system is ready to accept connections

Tarjimasi: "baza tizimi to'g'ri o'chirilmagan; avtomatik tiklash boshlandi", "jurnaldan qayta bajarish boshlandi", "baza ulanishlarni qabul qilishga tayyor". Log qisqartirildi; to'liq logda tiklash 0.10 soniya davom etgani yozilgan. Keyin tekshiruv:

text
  jami  | commit_qilingan | commit_qilinmagan
--------+-----------------+-------------------
 100001 |               1 |                 0
(1 row)

COMMIT qilingan qator — joyida (1). Qilinmagani — yo'q (0). Durability va atomicity birga ishladi: tasdiqlangan saqlandi, chala ish izsiz yo'qoldi. Kanon bu tajribani PostgreSQL 18.6, Docker Desktop (Windows 11, WSL2) da bir marta o'tkazgan.

Bu kafolat sozlamalarga bog'liq. Kanon serverida ular sukut holatida:

text
        name        | setting
--------------------+---------
 fsync              | on
 full_page_writes   | on
 synchronous_commit | on
 wal_level          | replica
(4 rows)

fsync = on — Postgres diskka "haqiqatan yoz" deb buyuradi. Uni off qilsa baza tezlashadi, lekin qulashda ma'lumot buzilishi mumkin. Internetdagi "Postgres'ni tezlashtirish" maslahatlarida bu tavsiya uchraydi — production'da bunday qilmang.

Tekshirib ko'ring: Ilova COMMIT yubordi, lekin javob kelishidan oldin tarmoq uzildi. Ma'lumot saqlanganmi?

Javob

Noma'lum. Ikki holat bo'lishi mumkin: COMMIT serverga yetib bormagan (saqlanmagan) yoki serverda bajarilgan, faqat javob yo'lda yo'qolgan (saqlangan). Ilova buni javobsiz bilolmaydi. Shuning uchun muhim amallar qayta yuborilganda ikki marta bajarilmasligi kerak — buni idempotentlik deyiladi (Idempotency-Key darsida). Durability faqat "javob keldi — saqlangan" ni kafolatlaydi.

4. BASE va eventual consistency

4.1 Ko'p server muammosi

Hozirgacha bitta server haqida gapirdik. Endi ma'lumot ikki shahardagi ikki serverda nusxalangan deylik: Toshkent va Samarqand. Aziz Toshkent serverida balansini o'zgartirdi. Samarqand serveri buni qachon biladi?

Ikki yo'l bor:

  1. Toshkent Samarqandning "oldim" javobini kutadi, keyin Aziz'ga "tayyor" deydi. Aniq, lekin sekin — har yozuv shaharlararo yo'lni kutadi.
  2. Toshkent darhol "tayyor" deydi va nusxani keyinroq yuboradi. Tez, lekin bir lahzada Samarqanddagi o'quvchi eski balansni ko'radi.

4.2 BASE

Ikkinchi yo'lning falsafasi — BASE:

  • Basically Available — tizim asosan ishlab turadi, javob beradi.
  • Soft state — holat vaqt o'tishi bilan o'zgarishi mumkin (nusxalar yetib kelayotgan bo'lishi mumkin).
  • Eventual consistency (oxir-oqibat izchillik) — yangi yozuvlar to'xtasa, hamma nusxa oxir-oqibat bir xil bo'ladi.

Kundalik misol: Telegram'da xabar yozdingiz, uni telefoningizda darhol ko'rasiz, kompyuterdagi Telegram'da esa bir soniyadan keyin. Yoki Instagram'dagi "like" soni: 1 203 yoki 1 204 — bir lahzalik farq hech kimga zarar bermaydi.

ACID va BASE — qarama-qarshi kimyoviy atamalar (kislota va asos) asosida tanlangan so'z o'yini. Qaysi biri yaxshi degan savol noto'g'ri: like soni uchun BASE yetadi, bank hisobi uchun ACID kerak.

Tekshirib ko'ring: Qaysi biriga eventual consistency yetadi: (a) YouTube video ko'rishlar soni, (b) aviachiptadagi bo'sh o'rinlar, (c) Telegram kanal obunachilari soni?

Javob

(a) va (c) — yetadi: raqam bir necha soniya kechiksa, hech kim zarar ko'rmaydi. (b) — yetmaydi: ikki serverda bir vaqtda oxirgi o'rin "bo'sh" ko'rinsa, ikki yo'lovchiga bitta joy sotiladi. Bunday joyda o'rinni band qilish aniq (ACID) bo'lishi kerak.

5. CAP teoremasi

5.1 Uch harf

2000-yilda Eric Brewer gipoteza aytdi, 2002-yilda Seth Gilbert va Nancy Lynch uni isbotladi. Ma'lumot ko'p serverga nusxalangan tizimda uchta xususiyat bor:

  • C — Consistency (izchillik): har o'qish eng oxirgi yozuvni ko'radi (yoki xato qaytaradi). Diqqat: bu ACID'dagi C emas — bu yerda "hamma nusxa bir xil" ma'nosida.
  • A — Availability (ishlab turish): ishlayotgan har server har so'rovga javob beradi.
  • P — Partition tolerance (bo'linishga chidamlilik): serverlar orasidagi tarmoq uzilsa ham tizim ishlashda davom etadi.

Teorema: tarmoq bo'linganda C va A dan faqat bittasini to'liq saqlash mumkin.

5.2 Nega "uchtadan ikkitasi" noto'g'ri

Ko'p maqolalarda "uchtadan ikkitasini tanlang" deyiladi. Bu chalg'itadi. Ko'p serverli tizimda tarmoq uzilishi bo'ladi — bu tanlov emas, haqiqat. Demak P majburiy. Savol faqat bitta: uzilish paytida nima qilamiz?

flowchart LR
  T[Toshkent<br/>server] x--x|tarmoq uzildi| S[Samarqand<br/>server]
  U[Foydalanuvchi] --> S
  S --> Q{Balans<br/>so'raldi}
  Q -->|CP| X[Xato: hozir<br/>aniq bilmayman]
  Q -->|AP| Y[Eski balansni<br/>beraman]

Nimaga qarang: Samarqand serveri Toshkentdan yangilik ololmayapti. CP tizim aniqlikni tanlaydi — "hozir javob bera olmayman" deydi. AP tizim ishlab turishni tanlaydi — javob beradi, lekin u eskirgan bo'lishi mumkin. Bank — CP, ijtimoiy tarmoq lentasi — AP.

Bitta serverli PostgreSQL'ga CAP to'g'ridan-to'g'ri tegishli emas — bo'linadigan tarmoq yo'q. U Postgres'ni nusxalab (replikatsiya) ko'p serverga qo'yganda dolzarb bo'ladi.

6. PACELC

2010-yilda Daniel Abadi CAP'ni to'ldirdi. Uning e'tirozi: CAP faqat uzilish paytini aytadi, lekin tizim vaqtining 99,9 % i uzilishsiz o'tadi. Shunda ham tanlov bor.

PACELC shunday o'qiladi: agar Partition (bo'linish) bo'lsa — A yoki C; Else (aks holda) — Latency (kechikish) yoki Consistency.

Holat Tanlov Misol
uzilish bor ishlab turish yoki aniqlik CAP'dagi savol
uzilish yo'q tezlik yoki aniqlik har yozuvda nusxani kutamizmi?

«Ko'p server muammosi» bo'limidagi ikki yo'lni eslang: Samarqand javobini kutish — aniq, lekin sekin (EC). Kutmaslik — tez, lekin bir lahza eski (EL). Bu tanlov tarmoq ishlab turganda ham bor.

PostgreSQL'da buni bitta sozlama ko'rsatadi: nusxa (replica) serverlar bilan ishlaganda synchronous_commit nusxa javobini kutish yoki kutmaslikni belgilaydi. Bu replikatsiya sozlamasini kanon sinamagan (bitta serverli o'rnatish) — faqat hujjat bo'yicha aytyapmiz.

Tekshirib ko'ring: Nega CAP'dagi C va ACID'dagi C har xil narsa?

Javob

ACID'dagi C — bazaning qoidalari (CHECK, UNIQUE, tashqi kalit) buzilmasligi, bitta serverda ham ma'noli. CAP'dagi C — ko'p nusxali tizimda har o'qish eng oxirgi yozuvni ko'rishi ("hamma nusxa bir xil"); bitta serverda bu savol umuman yo'q. Bir xil harf, ikki xil tushuncha — intervyularda tez-tez so'raladi.

7. SQL qadami: vazifalar qayerda tranzaksiyaga muhtoj

Bu darsda vazifalar sxemasiga kod qo'shilmaydi. Lekin qism davomida tranzaksiya kerak bo'ladigan joylarni oldindan belgilab qo'yamiz:

Amal Bir nechta buyruq Nega tranzaksiya
vazifa + uning teglari vazifa, teg, bog'lanish teglar chala qolmasin
vazifa o'chirilganda izohlari vazifa, izohlar yetim izoh qolmasin
tahrir + tarix yozuvi vazifa, tarix tarix haqiqatga mos bo'lsin

Kanon sxemasida bularning bir qismini bazaning o'zi bajaradi (tashqi kalit CASCADE, trigger'lar) — ular avtomatik ravishda o'sha buyruqning tranzaksiyasi ichida ishlaydi. Node.js'dan tranzaksiya ochishni Tranzaksiya asoslari darsida o'rganamiz.

8. Ko'p uchraydigan xatolar

8.1 current transaction is aborted ni asl xato deb o'ylash

Logda bu xabar ko'p qatorda takrorlanadi va dasturchi aynan uni qidiradi. Asl sabab — undan oldingi birinchi ERROR. Shu qatorni toping.

8.2 Tranzaksiyani yopmaslik

BEGIN qilindi, xato bo'ldi, kod ROLLBACK qilmadi. Ulanish "buzilgan" tranzaksiyada qoladi va keyingi hamma so'rov rad etiladi. Node.js'da bu klassik xato — uni Tranzaksiya asoslari darsida ko'rib chiqamiz.

8.3 Ikki alohida so'rovni "baribir birga bajariladi" deb o'ylash

BEGIN siz har buyruq o'z-o'zicha tranzaksiya (autocommit). Ikkita UPDATE orasida server qulasa — birinchisi saqlanadi, ikkinchisi yo'q. Bog'liq buyruqlar doim bitta tranzaksiyada.

8.4 fsync = off bilan "tezlashtirish"

Benchmark'da chiroyli raqam beradi. Birinchi elektr uzilishida esa baza buzilgan fayllar bilan qoladi. Bu sozlama faqat vaqtinchalik test bazasi uchun.

8.5 CAP'ni bitta serverga qo'llash

"Postgres CP" yoki "MongoDB AP" degan yorliqlar soddalashtirish: natija sozlamaga va tizim qanday o'rnatilganiga bog'liq. Bitta serverda CAP savoli umuman yo'q.

9. Mashqlar

Mashqlar kurs/mashqlar/26/07-acid/ da.

1-mashq (oson): harflarni juftlang

Har vaziyatga ACID harfini tanlang:

  1. Server qulab qayta yondi, tasdiqlangan buyurtmalar joyida.
  2. O'tkazmaning ikkinchi qadami yiqildi, birinchisi ham bekor bo'ldi.
  3. Hisobot o'tkazmaning yarim holatini ko'rmadi.
  4. Manfiy balansli qator CHECK tufayli bazaga kirmadi.
Yechim
  1. D — Durability (WAL tufayli).
  2. A — Atomicity (hammasi yoki hech narsa).
  3. I — Isolation (chala ish ko'rinmaydi).
  4. C — Consistency (qoida buzilmaydi).

2-mashq (o'rta): natijani oldindan ayting

Boshlanishda Aziz'da 100 000, Dilnoza'da 50 000 so'm. Har buyruqdan keyin psql nima deydi va oxirida balanslar qancha bo'ladi?

sql
BEGIN;
UPDATE t07_hisob SET balans = balans - 20000 WHERE ism = 'Aziz';
UPDATE t07_hisob SET balans = balans + 20000 WHERE ism = 'Dilnoza';
SELECT 1/0;
UPDATE t07_hisob SET balans = balans + 5000 WHERE ism = 'Dilnoza';
COMMIT;
Yechim
text
BEGIN
UPDATE 1
UPDATE 1
ERROR:  division by zero
ERROR:  current transaction is aborted, commands ignored until end of transaction block
ROLLBACK

Balanslar o'zgarmaydi: Aziz 100 000, Dilnoza 50 000. Birinchi ikki UPDATE bajarilgan edi, lekin 1/0 xatosi tranzaksiyani buzdi. To'rtinchi UPDATE rad etildi, COMMIT esa ROLLBACK ga aylandi — oldingi ikki o'zgarish ham bekor. Bu kanondagi «Xatodan keyin tranzaksiya "buzilgan"» tajribasi bilan bir xil qoida.

3-mashq (qiyin): «Bahor» kassasi

«Bahor» oshxonasida omborda 3 porsiya osh bor. Buyurtma ikki qadamdan iborat: buyurtmalar ga qator qo'shish va ombor dagi qoldiqni kamaytirish. Qoldiq manfiy bo'lolmaydi (CHECK). Ikki buyurtma keldi — har biri 2 porsiya osh. Har buyurtmani alohida tranzaksiyada bajaring. Oxirida buyurtmalar da nechta qator, omborda qancha osh qoladi? Tranzaksiyasiz nima bo'lardi?

Jadvallarni yaratish va INSERT yechim faylida; UPDATE — «Tajriba uchun jadval» bo'limidagi kabi.

Yechim
sql
BEGIN;
INSERT INTO buyurtmalar VALUES (1, 'osh', 2);
UPDATE ombor SET qoldiq = qoldiq - 2 WHERE taom = 'osh';
COMMIT;

BEGIN;
INSERT INTO buyurtmalar VALUES (2, 'osh', 2);
UPDATE ombor SET qoldiq = qoldiq - 2 WHERE taom = 'osh';
COMMIT;

SELECT * FROM buyurtmalar ORDER BY id;
SELECT * FROM ombor ORDER BY taom;

Natija (PostgreSQL 17.6):

text
ERROR:  new row for relation "ombor" violates check constraint "ombor_qoldiq_check"
DETAIL:  Failing row contains (osh, -1).
 id | taom | soni
----+------+------
  1 | osh  |    2
(1 row)

 taom  | qoldiq
-------+--------
 manti |     10
 osh   |      1
(2 rows)

Birinchi buyurtma to'liq o'tdi: qoldiq 3 → 1. Ikkinchisida UPDATE yiqildi (1 − 2 = −1), shuning uchun uning INSERT i ham bekor bo'ldi — buyurtmalar da bitta qator. Tranzaksiyasiz (BEGIN siz) ikkinchi buyurtma qatori saqlanib qolardi, osh esa ombordan ayirilmasdi: mijoz to'lagan, lekin oshxonada osh yo'q.

4-mashq: SQL qadami — o'z loyihangiz

DB turlari xaritasi va SQL vs NoSQL darsidagi loyihangizda bir nechta buyruq birga bajarilishi kerak bo'lgan ikkita amalni toping. Har biri uchun yozing: qaysi buyruqlar va biri yiqilsa nima buziladi.

Yechim

Namuna (portfolio). Birinchi: yangi post va uning teglarini saqlash — post saqlanib, teglar yiqilsa, post qidiruvda tegsiz qoladi. Ikkinchi: aloqa xabarini saqlash va "yangi xabarlar" hisoblagichini oshirish — biri yiqilsa, hisoblagich haqiqiy xabarlar soniga mos kelmaydi. Ikkalasida ham yechim: bitta tranzaksiya.

10. Real ishda

  • To'lov tizimlari: Payme, Click, Uzum kabi xizmatlar bilan integratsiyada har to'lov holati (yaratildi, tasdiqlandi, bekor qilindi) bazaga tranzaksiya ichida yoziladi. To'lovlarni keyingi qismlarda o'rganamiz — u yerda ACID har qadamda kerak bo'ladi.
  • Log va monitoring: current transaction is aborted va could not serialize access kabi xabarlar production loglarida eng ko'p uchraydiganlardan. Ularni o'qiy olish — tajribali backend dasturchi belgisi.
  • Intervyu savollari: "ACID'ni misol bilan tushuntiring", "CAP teoremasi nima, nega uchtadan ikkitasi degan gap noto'g'ri?", "Eventual consistency qayerda maqbul?". Kuchli javobda aniq misol bor: bank o'tkazmasi va like soni.

Xulosa

  • Tranzaksiya — bitta butun ish: BEGIN … COMMIT yoki ROLLBACK; xatodan keyingi COMMIT — ROLLBACK.
  • ACID: hammasi yoki hech narsa (A), qoidalar buzilmaydi (C), chala ish ko'rinmaydi (I), tasdiqlangan saqlanadi (D).
  • Durability'ni WAL beradi: kanonda SIGKILL'dan keyin tasdiqlangan qator qoldi (1), tasdiqlanmagani yo'qoldi (0).
  • BASE va eventual consistency — ko'p serverli tizimda tezlik va ishlab turish uchun aniqlikning bir lahzalik yo'qotilishi.
  • CAP: tarmoq bo'linganda aniqlik yoki ishlab turish; PACELC: bo'linish bo'lmaganda ham tezlik yoki aniqlik.

Keyingi dars: PostgreSQL o'rnatish va ulanish — o'z kompyuteringizda Postgres'ni Docker'da ko'tarib, unga ulanamiz.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
ACID, BASE, CAP va PACELC: baza qanday kafolat beradi — IlmHamroh