Transaction — ACID, BEGIN, COMMIT, ROLLBACK
Muammodan boshlaylik
Mijoz buyurtma berdi. Ilova uchta ishni bajaradi:
INSERT INTO buyurtmalar (mijoz_id) VALUES (2); -- 1. buyurtma
INSERT INTO buyurtma_qatorlari (...) VALUES (..., 5, 1, 3100000); -- 2. qator
UPDATE mahsulotlar SET soni = soni - 1 WHERE id = 5; -- 3. ombordan ayirish
2-qadamdan keyin server o'chib qoldi (yoki xato chiqdi). Natija:
- Buyurtma bor, qatori bor — lekin ombordan ayirilmagan
- Yoki: buyurtma yaratildi, lekin qatorlari yo'q — "bo'sh" buyurtma
Baza yarim-tayyor, o'ziga zid holatda qoldi. Bank o'tkazmasida bu yanada dahshatli: bir hisobdan pul yechildi, ikkinchisiga tushmadi.
Yechim — tranzaksiya: bir nechta amalni bitta bo'linmas birlik qilish. Yo hammasi bajariladi, yo hech biri.
Asosiy sintaksis
START TRANSACTION; -- yoki BEGIN;
INSERT INTO buyurtmalar (mijoz_id) VALUES (2);
SET @bid = LAST_INSERT_ID();
INSERT INTO buyurtma_qatorlari (buyurtma_id, mahsulot_id, soni, narx)
VALUES (@bid, 5, 1, 3100000);
UPDATE mahsulotlar SET soni = soni - 1 WHERE id = 5 AND soni >= 1;
COMMIT; -- hammasini saqlash
Xato bo'lsa:
ROLLBACK; -- hammasini bekor qilish — go'yo hech narsa bo'lmagandek
START TRANSACTIONvaCOMMITorasidagi o'zgarishlar boshqa ulanishlarga ko'rinmaydiCOMMIT— barcha o'zgarishlar bir lahzada doimiy bo'ladiROLLBACK— barchasi bekor qilinadi- Ulanish uzilsa yoki server o'chsa —
COMMITqilinmagan tranzaksiya avtomatikROLLBACK
Autocommit
Tranzaksiyasiz yozgan har bir so'rovingiz ham aslida tranzaksiya — avtomatik:
SELECT @@autocommit; -- 1
autocommit = 1 (standart) — har bir alohida so'rov o'z tranzaksiyasida va darhol COMMIT. START TRANSACTION bu rejimni COMMIT/ROLLBACK gacha vaqtincha o'chiradi.
[!WARNING] Ba'zi vositalar (masalan, Workbench sozlamalarida yoki ba'zi kutubxonalarda)
autocommit = 0bo'lishi mumkin. Unda sizUPDATEqilasiz, natijani ko'rasiz — lekin boshqalar ko'rmaydi, va ulanishni yopsangiz o'zgarish yo'qoladi. "Saqladim, lekin saqlanmadi" muammosining keng tarqalgan sababi.
ACID — tranzaksiyaning to'rt kafolati
A — Atomicity (bo'linmaslik)
"Hammasi yoki hech narsa". Uchta amaldan ikkitasi bajarilib, uchinchisi bajarilmagan holat bo'lmaydi.
C — Consistency (izchillik)
Tranzaksiya bazani bir to'g'ri holatdan boshqa to'g'ri holatga o'tkazadi. Barcha cheklovlar (FOREIGN KEY, UNIQUE, CHECK, NOT NULL) tranzaksiya oxirida bajarilgan bo'ladi. Biror cheklov buzilsa — tranzaksiya rad etiladi.
I — Isolation (alohidalik)
Bir vaqtda ishlayotgan tranzaksiyalar bir-biriga xalaqit bermaydi — go'yo navbat bilan bajarilgandek. Bir tranzaksiyaning yarim-tayyor o'zgarishlari boshqasiga ko'rinmaydi. (Darajalari — 37-dars.)
D — Durability (doimiylik)
COMMIT dan keyin ma'lumot saqlanadi — hatto keyingi soniyada quvvat o'chsa ham. InnoDB COMMIT paytida o'zgarishni avval diskdagi jurnalga (redo log) yozadi, keyin "tayyor" deydi.
| Harf | Kafolat | Busiz nima bo'ladi |
|---|---|---|
| A | Hammasi yoki hech narsa | Yarim-tayyor buyurtmalar |
| C | Qoidalar buzilmaydi | Mavjud bo'lmagan mijozga buyurtma |
| I | Parallel tranzaksiyalar xalaqit bermaydi | Bitta mahsulot ikki kishiga sotiladi |
| D | Saqlangan — saqlangan | COMMIT dan keyin ma'lumot yo'qoladi |
Xatoni boshqarish
MySQL da xato chiqqanda tranzaksiya avtomatik bekor qilinmaydi — faqat xato bergan so'rov bekor qilinadi:
START TRANSACTION;
INSERT INTO buyurtmalar (mijoz_id) VALUES (2); -- ✅
INSERT INTO buyurtmalar (mijoz_id) VALUES (9999); -- ❌ foreign key xatosi
COMMIT; -- birinchi INSERT saqlanadi!
Shuning uchun xato bo'lganda o'zingiz ROLLBACK qilishingiz kerak. Bu ilova kodida qilinadi:
<?php
// PHP + PDO
$pdo->beginTransaction();
try {
$pdo->prepare('INSERT INTO buyurtmalar (mijoz_id) VALUES (?)')->execute([$mijozId]);
$bid = $pdo->lastInsertId();
$pdo->prepare('INSERT INTO buyurtma_qatorlari (buyurtma_id, mahsulot_id, soni, narx) VALUES (?, ?, ?, ?)')
->execute([$bid, $mahsulotId, $soni, $narx]);
$stmt = $pdo->prepare('UPDATE mahsulotlar SET soni = soni - ? WHERE id = ? AND soni >= ?');
$stmt->execute([$soni, $mahsulotId, $soni]);
if ($stmt->rowCount() === 0) {
throw new RuntimeException('Omborda yetarli emas');
}
$pdo->commit();
} catch (Throwable $e) {
$pdo->rollBack();
throw $e;
}
// Node.js + mysql2
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
// ... so'rovlar
await conn.commit();
} catch (e) {
await conn.rollback();
throw e;
} finally {
conn.release();
}
E'tibor bering: omborda yetarli bo'lmasa — bu SQL xatosi emas (UPDATE shunchaki 0 qatorni o'zgartiradi). Biznes qoidasi buzilganini ilova tekshiradi va ROLLBACK qiladi.
Nima tranzaksiyani yakunlaydi
COMMIT va ROLLBACK dan tashqari, ba'zi buyruqlar yashirin COMMIT qiladi (8-dars):
START TRANSACTION;
UPDATE mahsulotlar SET narx = 1 WHERE id = 1;
ALTER TABLE mahsulotlar ADD COLUMN x INT; -- ← yashirin COMMIT!
ROLLBACK; -- UPDATE qaytmaydi
CREATE, ALTER, DROP, TRUNCATE, RENAME, LOCK TABLES — tranzaksiya ichida ishlatmang.
Tranzaksiyalarni qisqa tuting
❌ START TRANSACTION
→ mahsulotni o'qish
→ to'lov tizimiga HTTP so'rov (3 soniya)
→ email yuborish (2 soniya)
→ buyurtmani yozish
COMMIT
Tranzaksiya ochiq turgan har bir soniya — qulflar ushlab turiladi (38-dars), boshqa so'rovlar kutadi. Sekin tashqi amallarni (HTTP, email, fayl) tranzaksiyadan tashqarida bajaring:
✅ to'lov tizimiga so'rov
START TRANSACTION
→ buyurtmani yozish, ombordan ayirish
COMMIT
→ email yuborish (yoki navbatga qo'yish)
Qaysi jadvallar tranzaksiyani qo'llab-quvvatlaydi
Faqat InnoDB (MySQL 8 da standart). Eski MyISAM jadvallari tranzaksiyani qo'llab-quvvatlamaydi — ROLLBACK ularga ta'sir qilmaydi, jimgina.
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'dokon';
Eski loyihani olsangiz va ENGINE = MyISAM ko'rsangiz:
ALTER TABLE eski_jadval ENGINE = InnoDB;
Nima uchun shunday?
Nima uchun xato chiqqanda MySQL butun tranzaksiyani o'zi bekor qilmaydi?
Chunki ba'zan xato kutilgan va qayta ishlanadigan bo'ladi. Masalan: INSERT dublikat xatosi berdi — ilova uni ushlab, UPDATE ga o'tadi va tranzaksiyani davom ettiradi. Agar MySQL har xatoda hammasini bekor qilsa, bunday mantiq imkonsiz bo'lardi. MySQL qarorni sizga qoldiradi: davom etish yoki ROLLBACK. (PostgreSQL boshqacha yo'l tanlagan: xatodan keyin tranzaksiya "buzilgan" holatga o'tadi va faqat ROLLBACK qabul qiladi.)
Xulosa
Eslab qoling:
START TRANSACTION...COMMIT/ROLLBACK— hammasi yoki hech narsa- ACID: Atomicity, Consistency, Isolation, Durability
autocommit = 1— har bir so'rov o'z-o'zidan tranzaksiya- Xato tranzaksiyani avtomatik bekor qilmaydi — ilovada
try/catch+rollBack() - DDL (
ALTER,CREATE,DROP) — yashirinCOMMIT - Tranzaksiyani qisqa tuting; HTTP, email — tashqarida
- Faqat InnoDB; MyISAM tranzaksiyani bilmaydi
Keyingi dars
37-dars: Isolation Levels — READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE