Transaction — ACID, BEGIN, COMMIT, ROLLBACK, SAVEPOINT
Bank o'tkazmasi: A hisobdan 100 000 so'm chiqariladi, B hisobga 100 000 so'm qo'shiladi. Birinchi SQL bajarildi — ikkinchisi bajarilishdan oldin server ishdan chiqdi:
UPDATE hisoblar SET balans = balans - 100000 WHERE id = 1; -- bajarildi
-- Server ishdan chiqdi!
UPDATE hisoblar SET balans = balans + 100000 WHERE id = 2; -- bajarilmadi
100 000 so'm yo'qoldi. Transaction — bu ikki SQL yoki ikkalasi bajariladi, yoki hech biri.
ACID
Transaction to'rtta kafolat beradi:
A — Atomicity — yoki hammasi, yoki hech biri
C — Consistency — ma'lumot har doim to'g'ri holatda
I — Isolation — tranzaksiyalar bir-biriga xalaqit bermaydi
D — Durability — COMMIT dan keyin ma'lumot saqlanadi
BEGIN, COMMIT, ROLLBACK
BEGIN; -- tranzaksiya boshlash
UPDATE hisoblar SET balans = balans - 100000 WHERE id = 1;
UPDATE hisoblar SET balans = balans + 100000 WHERE id = 2;
COMMIT; -- ikkalasi birda saqlanadi
Xato bo'lsa — bekor qilish:
BEGIN;
UPDATE hisoblar SET balans = balans - 100000 WHERE id = 1;
-- Xato yuz berdi!
ROLLBACK; -- hech narsa o'zgarmaydi, balans qaytariladi
Avtomatik tranzaksiya
Har SQL aslida tranzaksiya ichida bajariladi — PostgreSQL avtomatik BEGIN/COMMIT qo'shadi:
-- Bu ikki so'rov alohida tranzaksiyalar
DELETE FROM eski_qatorlar WHERE id = 1; -- avtomatik COMMIT
DELETE FROM eski_qatorlar WHERE id = 2; -- avtomatik COMMIT
Bir tranzaksiyada bajarish uchun BEGIN ... COMMIT qo'lda yoziladi.
SAVEPOINT — qisman orqaga qaytish
Katta tranzaksiya ichida oraliq nuqta:
BEGIN;
INSERT INTO buyurtmalar (summa) VALUES (50000);
SAVEPOINT birinchi_qism;
INSERT INTO buyurtma_elementlari (nomi) VALUES ('Noutbuk');
-- Bu yerda xato!
ROLLBACK TO SAVEPOINT birinchi_qism;
-- Faqat ikkinchi INSERT bekor — birinchisi saqlanadi
INSERT INTO buyurtma_elementlari (nomi) VALUES ('Telefon');
COMMIT;
Node.js da transaction
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query(
'UPDATE hisoblar SET balans = balans - $1 WHERE id = $2',
[100000, 1]
);
await client.query(
'UPDATE hisoblar SET balans = balans + $1 WHERE id = $2',
[100000, 2]
);
await client.query('COMMIT');
} catch (err) {
await client.query('ROLLBACK');
throw err;
} finally {
client.release();
}
Tez-tez uchraydigan xatolar
COMMIT / ROLLBACK unutish:
BEGIN;
UPDATE ...;
-- COMMIT yo'q — session yopilganda avtomatik ROLLBACK
-- Boshqa sessialar bu o'zgarishni ko'rmaydi!
Tranzaksiya ichida uzoq operatsiya:
BEGIN;
-- Ko'p vaqt oluvchi hisoblash...
UPDATE jadval SET ... ; -- Lock ushlab turadi!
COMMIT;
Tranzaksiya qisqa bo'lishi kerak — lock ushlab turish boshqa so'rovlarni bloklaydi.
Xulosa
BEGIN; -- tranzaksiya boshlash
SQL1; SQL2; SQL3; -- operatsiyalar
COMMIT; -- saqlanadi
-- yoki
ROLLBACK; -- bekor qilinadi
SAVEPOINT nom; -- oraliq nuqta
ROLLBACK TO SAVEPOINT nom; -- nuqtaga qaytish
RELEASE SAVEPOINT nom; -- nuqtani o'chirish
ACID: Atomicity — hammasi yoki hech biri. Durability — COMMIT dan keyin har doim saqlanadi.
Keyingi dars
45-dars: Isolation Levels — Read Committed, Repeatable Read, Serializable