Tranzaksiyalar, qulflar va poyga (race condition)
lockThis content isn't available in English yetAvailable in: O'zbek
terminal
Hands-on labs
Interactive tasks attached to this lesson — complete them in a real Kubernetes environment and check the result.
terminal
PostgreSQL: tranzaksiya atomikligi (BEGIN / COMMIT / ROLLBACK)
Osonbolt+20 XP
Pul o'tkazish IKKI amaldan iborat: bittasidan ayirish, boshqasiga qo'shish. Agar ikkinchisi yiqilsa va birinchisi saqlanib qolsa — pul YO'QOLADI. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/otkazma.sql skriptini yozing: hisob jadvalida id = 1 dan id = 2 ga 300 o'tkazsin. ⚠Skript ATOMAR bo'lishi SHART: ikkinchi amal xato bersa, birinchisi ham BEKOR bo'lishi kerak. Jadvalda check (balans = 0 and balans <= 5000) bor. Checker skriptni ikki holatda ishga tushiradi: (a) oddiy holat, (b) qabul qiluvchining balansi 4900 — bunda +300 constraint'ni buzadi va HECH NARSA o'zgarmasligi kerak. Muvaffaqiyat mezoni (jonli) Oddiy holatda: 700 va 1300 Constraint buzilgan holatda: id = 1 balansi O'ZGARMAGAN (1000) va umumiy summa saqlangan
terminal
PostgreSQL: idempotent UPSERT (INSERT ... ON CONFLICT DO UPDATE)
Murakkabbolt+30 XP
Sozlama yozuvi bir vaqtda bir necha jarayon tomonidan yangilanadi. "Avval tekshir, keyin qo'sh" naqshi poygada ikki qator yaratib qo'yadi. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/upsert.sql skriptini yozing: sozlama jadvaliga kalit = 'rejim', qiymat = 'ishlab' yozuvini qo'shsin. Agar kalit ALLAQACHON bor bo'lsa: qiymat yangilansin va yangilangan hisoblagichi 1 ga oshsin. ⚠Checker skriptni BIR VAQTDA 5 marta ishga tushiradi: natijada aynan BITTA qator bo'lishi va hisoblagich aynan 4 bo'lishi kerak. Muvaffaqiyat mezoni (jonli) 5 parallel bajarilishda birorta ham xato yo'q; jadvalda aynan 1 qator; yangilangan = 4; qiymat = 'ishlab'
terminal
PostgreSQL: poygaga chidamli kamaytirish (atomar UPDATE + CHECK)
Murakkabbolt+30 XP
Omborda 10 dona mahsulot bor, lekin 20 xaridor bir vaqtda buyurtma beryapti. Qoldiq HECH QACHON manfiy bo'lmasligi kerak. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/olish.sql skriptini yozing: disk mahsulotining qoldig'ini 1 ga kamaytirsin. ⚠Checker skriptni BIR VAQTDA 20 marta ishga tushiradi. Qoldiq 10 — ya'ni aynan 10 ta bajarilish MUVAFFAQIYATLI, 10 tasi XATO bilan tugashi kerak. Jadvalda check (qoldiq = 0) bor. ⚠Avval select bilan o'qib, keyin set qoldiq = deb yozish POYGAGA chidamsiz — invariant buziladi. Muvaffaqiyat mezoni (jonli) 20 parallel bajarilishda aynan 10 muvaffaqiyat va 10 xato; oxirgi qoldiq AYNAN 0 (manfiy emas, ortiq emas)
terminal
PostgreSQL: SELECT ... FOR UPDATE — o'qi-keyin-yoz naqshini himoyalash
Murakkabbolt+30 XP
Ba'zan qiymatni AVVAL o'qish, dasturda hisoblash va KEYIN yozish kerak bo'ladi. Bu ikki qadam orasida boshqa sessiya qiymatni o'zgartirsa — hisob-kitob eskirgan ma'lumotga asoslanadi. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/olish.sql skriptini yozing. U do $$ ... $$ blokida: disk qoldig'ini o'zgaruvchiga O'QISIN perform pg sleep(0.02) bilan hisob-kitobni imitatsiya qilsin Keyin qoldiqni o'qilgan qiymat - 1 ga TENGLASHTIRSIN (set qoldiq = v - 1, qoldiq - 1 EMAS) ⚠Bu naqsh poygaga chidamsiz. Uni for update bilan himoyalang. ⚠Qoldiq 20, checker 20 parallel ishga tushiradi: hammasi muvaffaqiyatli tugashi va oxirgi qoldiq AYNAN 0 bo'lishi kerak. Muvaffaqiyat mezoni (jonli) 20 parallel bajarilishda 20 muvaffaqiyat; oxirgi qoldiq AYNAN 0; skriptda for update ishlatilgan
terminal
PostgreSQL: izolyatsiya darajasi — REPEATABLE READ snapshot
Murakkabbolt+30 XP
Hisobot ikki marta bir xil qiymatni o'qiydi. Ular orasida boshqa sessiya qiymatni o'zgartirsa, hisobot O'ZINI ZIDDIGA tushadi: bir sahifada 100, ikkinchisida 999. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/oqish.sql skriptini yozing: Tranzaksiyani REPEATABLE READ izolyatsiya darajasida boshlang narx dan id = 1 qiymatini o'qib kuzatuv ga ('birinchi', ) qo'shing select pg sleep(0.5) Yana o'qib ('ikkinchi', ) qo'shing commit ⚠Checker skript ishlayotgan payt PARALLEL sessiyada narx ni 999 ga o'zgartiradi. Ikki o'qish ham BIR XIL qiymatni (100) ko'rishi kerak. Muvaffaqiyat mezoni (jonli) kuzatuv da 2 qator; ikkovining qiymati BIR XIL va 100 ga teng; shu bilan birga narx jadvalida qiymat haqiqatan 999 ga o'zgargan
terminal
PostgreSQL: deadlock — sababi va tuzatilishi
Murakkabbolt+30 XP
Ikki skript ikki hisob o'rtasida pul o'tkazadi, lekin qulflarni TESKARI tartibda oladi. Parallel ishlaganda ular bir-birini kutib qotib qoladi va PostgreSQL birini majburan yiqitadi (deadlock detected). Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/a.sql va /root/db/b.sql skriptlari SEED tomonidan yaratilgan: a.sql: avval id = 1 ni yangilaydi, keyin id = 2 ni b.sql: avval id = 2 ni yangilaydi, keyin id = 1 ni Ikkovini TUZATING: qulflar DOIM bir xil tartibda (id o'sish bo'yicha) olinsin. Har skript baribir 10 birlik o'tkazishi kerak — a.sql 1 dan 2 ga, b.sql 2 dan 1 ga. ⚠Checker ikkovini 5 juft qilib parallel ishga tushiradi: BIRORTA ham xato bo'lmasligi va umumiy summa saqlanishi kerak. Muvaffaqiyat mezoni (jonli) 5 juft parallel bajarilishda 0 xato; deadlock xabari YO'Q; umumiy summa 2000; har skript hamon 10 birlik o'tkazadi
terminal
PostgreSQL: bloklangan sessiyalarni topish (pg_blocking_pids)
Murakkabbolt+30 XP
Ilova "qotib qoldi" degan shikoyat keldi. Sababi ko'pincha uzun tranzaksiya qulfni ushlab turgani — buni bir so'rov bilan aniqlash mumkin. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/query.sql fayliga so'rov yozing: HOZIR boshqa sessiya tomonidan BLOKLANGAN sessiyalar SONINI qaytarsin (bitta son). Maslahat: pg blocking pids(pid) funksiyasi sessiyani bloklab turgan pid lar massivini qaytaradi — massiv bo'sh bo'lmasa, sessiya bloklangan. ⚠Checker so'rovni IKKI holatda ishga tushiradi: (a) jonli blokirovka yaratilgan paytda — natija 1 bo'lishi kerak; (b) blokirovka yo'q paytda — natija 0. Ya'ni qotirilgan javob o'tmaydi. Muvaffaqiyat mezoni (jonli) Jonli blokirovka paytida so'rov 1 qaytaradi; blokirovka yo'q paytda 0
terminal
PostgreSQL: idempotent to'lov (bir marta hisoblanishi kafolati)
Murakkabbolt+30 XP
To'lov xizmati bir xil webhook'ni bir necha marta yuborishi mumkin (qayta urinish, tarmoq uzilishi). Pul FAQAT BIR MARTA hisoblanishi kerak. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/tolov.sql skriptini yozing: tolov jadvaliga kalit = 'CHRG-1', summa = 500 yozuvini qo'shsin — lekin kalit allaqachon bo'lsa HECH NARSA qilmasin Va FAQAT yangi yozuv qo'shilgan bo'lsa hamyon balansini 500 ga oshirsin ⚠Checker skriptni BIR VAQTDA 30 marta ishga tushiradi. Natija: tolov da aynan 1 qator, balans aynan 500, va birorta ham xato bo'lmasligi kerak. Maslahat: with ... as (insert ... on conflict do nothing returning ...) — CTE ichidagi insert natijasiga qarab update qilish mumkin. Muvaffaqiyat mezoni (jonli) 30 parallel bajarilishda 0 xato; tolov jadvalida aynan 1 qator; hamyon balansi AYNAN 500 (ikki marta hisoblanmagan)
terminal
PostgreSQL: navbatdan vazifa olish — FOR UPDATE SKIP LOCKED (D temasi yakuni)
Murakkabbolt+30 XP
20 ta ishchi jarayon bitta navbat jadvalidan vazifa oladi. Har vazifa AYNAN BIR ishchiga tegishi kerak: dublikat — ish ikki marta bajarilishi, bloklanish esa butun navbatning to'xtab qolishi. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/ol.sql skriptini yozing: navbat jadvalidan holat = 'yangi' bo'lgan ENG KICHIK id li BITTA vazifani olib, uni 'olindi' ga o'tkazsin va returning bilan id ni qaytarsin. ⚠Checker skriptni BIR VAQTDA 20 marta ishga tushiradi. Navbatda 20 vazifa bor — HAMMASI olinishi kerak (yangi qolmasin), birorta xato bo'lmasin. Maslahat: for update skip locked — band qatorni KUTMASDAN tashlab o'tadi, shu bilan har ishchi BOSHQA vazifani oladi. Muvaffaqiyat mezoni (jonli) 20 parallel bajarilishda 0 xato; olindi soni AYNAN 20; yangi holatda 0 vazifa qolgan; skriptda skip locked ishlatilgan
terminal
PostgreSQL: SAVEPOINT — tranzaksiya ichida qismiy bekor qilish
Osonbolt+20 XP
Uchta qator qo'shilishi kerak, lekin o'rtadagisi mavjud kalitni takrorlaydi. Oddiy tranzaksiyada bu XATO butun ishni bekor qiladi — birinchi va uchinchi qator ham saqlanmaydi. Ish katalogi: /root/db/. Bazada HAQIQIY PostgreSQL 16 ishlaydi (unix socket, psql -h /tmp -d hn). Checker JONLI tekshiradi: so'rov NATIJASI, katalog holati (pg indexes, pg constraint, pg roles), EXPLAIN (format json) rejasi va ma'lumotning haqiqiy o'zgarishi. ⚠psql ni postgres foydalanuvchisi ostida chaqirish kerak: su postgres -c "psql -h /tmp -d hn -c '...'" yoki -f fayl.sql. ⚠Server root ostida ishlamaydi — shuning uchun barcha psql chaqiruvlari postgres foydalanuvchisi nomidan bajariladi. Vazifa /root/db/kirit.sql skriptini yozing: BITTA tranzaksiyada jurnal jadvaliga uch qator qo'shilsin — (1, 'bir'), (2, 'ikki'), (3, 'uch'). ⚠Jadvalda id = 2 ALLAQACHON bor (mavjud matni bilan) — u qatorga insert XATO beradi. Skript SAVEPOINT ishlatib shu xatoni yutib yuborsin: 1 va 3 qatorlar SAQLANSIN, tranzaksiya commit bilan tugasin. ⚠on conflict ISHLATMANG — bu lab savepoint mexanizmi haqida. Muvaffaqiyat mezoni (jonli) Jadvalda aynan 3 qator; id = 1 matni bir, id = 3 matni uch; id = 2 matni hamon mavjud (o'zgarmagan)
