Asosiy kontentga o‘tish
Innovialabs

Ma’lumotlar bazasida tranzaksiyalar va ACID oddiy tilda

Asoslar4 daq

Qisqacha

Tranzaksiya bazadagi bir nechta amalni «hammasi yoki hech biri» tamoyilidagi yagona birlikka birlashtiradi; ACID uning to‘liq bajarilishi yoki umuman bajarilmasligini (atomarlik), ma’lumotlarni to‘g‘ri saqlashini (izchillik), parallel tranzaksiyalar bilan aralashmasligini (izolyatsiya) va qayd etilgach nosozlikdan omon qolishini (barqarorlik) anglatadi.

Qisqacha javob

Tranzaksiya — birga bajarilishi yoki birga bajarilmasligi kerak bo‘lgan bazadagi amallar guruhi. Klassik misol — pul o‘tkazmasi: Alisherdan 100 yechib, Boburga 100 qo‘shish. Agar server shu ikki qadam orasida ishdan chiqsa, pul yo‘qolib qolmasligi kerak.

ACID — buni xavfsiz qiladigan to‘rtta kafolat:

HarfXususiyatO‘tkazma misolida
AAtomarlik (Atomicity)Ikkala yangilanish bajariladi yoki hech biri
CIzchillik (Consistency)Qoida taqiqlasa, balans minusga tushmaydi
IIzolyatsiya (Isolation)Parallel o‘tkazma chala ma’lumotni ko‘rmaydi
DBarqarorlik (Durability)«Muvaffaqiyatli»dan keyin o‘tkazma tok o‘chishidan ham omon qoladi

O‘tkazma SQL’da

BEGIN;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;  -- Alisher
UPDATE accounts SET balance = balance + 100 WHERE id = 2;  -- Bobur

COMMIT;
  • BEGIN (yoki START TRANSACTION) tranzaksiyani ochadi.
  • COMMIT barcha o‘zgarishlarni qayd etadi va boshqalarga ko‘rinadigan qiladi.
  • ROLLBACK BEGINdan keyin qilingan hamma narsani bekor qiladi.

Agar o‘rtada biror narsa noto‘g‘ri ketsa, ROLLBACK bajariladi va baza o‘tkazmadan oldingi holatga qaytadi.

Atomarlik: hammasi yoki hech narsa

Baza tranzaksiya ichidagi har bir o‘zgarishni kuzatib boradi. Tranzaksiya bekor qilinsa yoki ulanish COMMITgacha uzilsa, o‘zgarishlar tashlab yuboriladi. Alisherdan 100 yechilgan-u, Bobur uni olmagan holat bo‘lmaydi.

Izchillik: qoidalar doim bajariladi

Izchillik tranzaksiya bazani bir to‘g‘ri holatdan boshqa to‘g‘ri holatga o‘tkazishini anglatadi. «To‘g‘rilik»ni sizning cheklovlaringiz belgilaydi:

ALTER TABLE accounts
  ADD CONSTRAINT balance_not_negative CHECK (balance >= 0);

Agar Alisherda faqat 50 bo‘lsa, birinchi UPDATE tekshiruvni buzadi, operator xato bilan tugaydi va tranzaksiyani qayd etib bo‘lmaydi. Tashqi kalitlar, NOT NULL va UNIQUE ham shunday ishlaydi. Baza siz e’lon qilgan qoidalarni kuzatadi; e’lon qilinmagan biznes qoidalari ilovaning vazifasi bo‘lib qoladi.

Izolyatsiya: parallel tranzaksiyalar bir-biriga xalaqit bermaydi

Real tizimda bir vaqtda ko‘plab tranzaksiyalar bajariladi. Izolyatsiyasiz Alisher hisobidan ikkita o‘tkazma ikkalasi ham balansni 100 deb o‘qishi, ikkalasi ham 100 dan yechishi va hisobni noto‘g‘ri holatda qoldirishi mumkin edi.

Bazalar izolyatsiya darajalarini taklif qiladi — kuchsiz va tezdan qat’iyroqqacha:

DarajaNimadan himoya qiladi
Read UncommittedDeyarli hech narsadan; qayd etilmagan ma’lumotni o‘qish mumkin
Read CommittedIflos o‘qishdan: faqat qayd etilgan ma’lumot ko‘rinadi
Repeatable ReadTakrorlanmas o‘qishdan ham: o‘qilgan qator ishlayotganingizda o‘zgarmaydi
SerializableFantomlardan ham: natija xuddi tranzaksiyalar navbat bilan bajarilgandek

Standart qiymatlar farq qiladi: PostgreSQL’da — Read Committed, InnoDB bilan MySQL’da — Repeatable Read. Har bir darajadagi aniq xatti-harakat ham MBBTlar orasida farqlanadi, shuning uchun o‘z bazangiz hujjatlarini tekshiring.

Read Committed darajasidagi o‘tkazma uchun o‘zgartiradigan qatorlaringizni bloklang:

BEGIN;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- balansni ilovada tekshiramiz, keyin:
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

FOR UPDATE xuddi shu hisobdan ikkinchi o‘tkazmani birinchisi tugaguncha kutishga majbur qiladi.

Barqarorlik: qayd etildi — demak saqlandi

COMMIT muvaffaqiyat qaytarganda o‘zgarish diskdagi ishonchli jurnalga yozilgan bo‘ladi (PostgreSQL’da bu WAL, write-ahead log, InnoDB’da — redo log). Nosozlikdan keyin baza jurnalni qayta o‘ynaydi va qayd etilgan ma’lumotlarni tiklaydi. Barqarorlik server qayta ishga tushishidan himoya qiladi, lekin diskning o‘zi yo‘qolishidan emas — buning uchun bekaplar va replikalar kerak.

Ilova kodidagi tranzaksiyalar

Ko‘pchilik drayverlar va ORM’lar bu shablonni siz uchun o‘rab beradi. G‘oya hamma joyda bir xil:

with conn:                      # tranzaksiyani ochadi
    with conn.cursor() as cur:
        cur.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s", (100, 1))
        cur.execute("UPDATE accounts SET balance = balance + %s WHERE id = %s", (100, 2))
# muvaffaqiyatda commit, istisnoda rollback

Ko‘p uchraydigan xatolar

  • Kutilmagan autocommit: aniq tranzaksiyasiz har bir operator o‘zi qayd etiladi va ikki yangilanish orasidagi nosozlik yarim o‘tkazmani qoldiradi.
  • Uzoq tranzaksiyalar: foydalanuvchi yoki tashqi API’ni kutib tranzaksiyani ochiq ushlab turish bloklarni ushlab, boshqalarni sekinlashtiradi.
  • Tranzaksiya ichida tashqi servislarni chaqirish: bekor qilish yuborilgan SMS yoki to‘lov so‘rovini qaytarmaydi.
  • Qayta urinishlarning yo‘qligi: Serializable darajasida yoki o‘zaro bloklanishda (deadlock) baza tranzaksiyani ataylab to‘xtatishi mumkin — ilova uni qayta bajarishi kerak.

Ko‘p beriladigan savollar

Ko‘pchiligi u yoki bu darajada. Masalan, MongoDB bir nechta hujjat ustida tranzaksiyalarni qo‘llab-quvvatlaydi, Redis’da esa boshqa kafolatlarga ega o‘z MULTI/EXEC mexanizmi bor. Bazaga pul yoki qoldiqlarni ishonib topshirishdan oldin u aynan nimani va’da qilishini tekshiring.

Bunda yordam beramiz

O‘zingiz shug‘ullanmasdan natija olishni istasangiz — biz har kuni shu bilan shug‘ullanamiz.

Loyihani muhokama qilish

Yana o‘qing

G‘oya yoki vazifangiz bormi? Bizga aytib bering

Ish kuni davomida javob beramiz va yechim taklif qilamiz. Konsultatsiya bepul.