Tranzaksiya β bir guruh amallar birgalikda muvaffaqiyatli yoki umuman bajarilmaydi.
ACID xususiyatlari
- Atomicity β ya hammasi, ya hech narsa
- Consistency β ma'lumot har doim to'g'ri holatda
- Isolation β tranzaksiyalar bir-biriga ta'sir qilmaydi
- Durability β commit qilingan ma'lumot yo'qolmaydi
Tranzaksiya sintaksisi
BEGIN; -- yoki START TRANSACTION;
UPDATE hisoblar SET balans = balans - 500000 WHERE id = 1;
UPDATE hisoblar SET balans = balans + 500000 WHERE id = 2;
COMMIT; -- Ikkala o'zgarish saqlanadi
ROLLBACK β bekor qilish
BEGIN;
UPDATE hisoblar SET balans = balans - 500000 WHERE id = 1;
-- Xato bo'ldi!
ROLLBACK; -- Hamma narsa asl holiga qaytadi
SAVEPOINT
BEGIN;
INSERT INTO buyurtmalar VALUES (1, 'Python kursi', 500000);
SAVEPOINT birinchi_bosqich;
INSERT INTO to'lovlar VALUES (1, 500000, NOW());
-- Bu o'zgarishni bekor qilish
ROLLBACK TO birinchi_bosqich;
-- Buyurtma saqlanadi, to'lov yo'q
COMMIT;
Izolyatsiya darajalari
-- Read Committed (default PostgreSQL)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- Serializable (eng yuqori himoya)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Read Uncommitted (eng past himoya)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Amaliy misol: Bank o'tkazmasi
CREATE OR REPLACE FUNCTION pul_o'tkaz(
yuboruvchi_id INT,
qabul_qiluvchi_id INT,
miqdor DECIMAL
) RETURNS VOID AS $$
BEGIN
-- Balansni tekshirish
IF (SELECT balans FROM hisoblar WHERE id = yuboruvchi_id) < miqdor THEN
RAISE EXCEPTION 'Balans yetarli emas';
END IF;
UPDATE hisoblar SET balans = balans - miqdor WHERE id = yuboruvchi_id;
UPDATE hisoblar SET balans = balans + miqdor WHERE id = qabul_qiluvchi_id;
INSERT INTO tarixi (yuboruvchi, qabul_qiluvchi, miqdor, vaqt)
VALUES (yuboruvchi_id, qabul_qiluvchi_id, miqdor, NOW());
END;
$$ LANGUAGE plpgsql;