Transaction ба ACID
Банкны шилжүүлгийг төсөөлөөрэй: таны дансны мөнгийг хасаж, найзынхад нэмнэ. Хэрэв мөнгийг хасчихаад тасалдал гарвал найзынх нэмэгдэхгүй — мөнгө алга болно. Transaction нь энэ асуудлыг шийддэг: бүлэг үйлдлүүдийг нэг нэгж болгон гүйцэтгэж, бүгд амжилттай болох эсвэл бүгдийг цуцлах баталгаа өгдөг.
Transaction үндэс
BEGIN — COMMIT хооронд бичигдсэн бүх SQL үйлдэл нэг transaction болно:
-- Жишээ: дансны мөнгө шилжүүлэх
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
owner TEXT NOT NULL,
balance NUMERIC NOT NULL CHECK (balance >= 0)
);
INSERT INTO accounts (owner, balance) VALUES ('Болд', 500000), ('Сарнай', 200000);
-- Transaction эхлүүлэх
BEGIN;
-- Болдын дансаас хасах
UPDATE accounts SET balance = balance - 100000 WHERE owner = 'Болд';
-- Сарнайн данст нэмэх
UPDATE accounts SET balance = balance + 100000 WHERE owner = 'Сарнай';
-- Бүх үйлдлийг баталгаажуулах
COMMIT;
-- Шалгах
SELECT owner, balance FROM accounts;
-- Болд: 400000 | Сарнай: 300000
COMMIT хийхээс өмнө гаднаас харвал өөрчлөлт харагдахгүй — зөвхөн transaction дотроос харагдана.
ROLLBACK — цуцлах
Ямар нэгэн алдаа гарвал ROLLBACK гүйцэтгэн бүх өөрчлөлтийг буцааж болно:
BEGIN;
UPDATE accounts SET balance = balance - 999999 WHERE owner = 'Болд';
-- Болдын дансанд 500000 ₮ л байна, хасалт хэтэрч байна!
-- Алдаа илрэв, бүхнийг цуцлах
ROLLBACK;
-- Болдын данс хэвээрээ
SELECT balance FROM accounts WHERE owner = 'Болд';
-- 500000
CHECK (balance >= 0) хязгаарлалтаас болж алдаа гарвал PostgreSQL автоматаар transaction-г цуцалдаг. Гэвч алдааг гараар илрүүлж ROLLBACK хийх нь илүү тодорхой код болдог.
SAVEPOINT — дундын цэг
Transaction дотор SAVEPOINT тавьж, бүгдийг биш зарим хэсгийг л цуцлах боломжтой:
BEGIN;
INSERT INTO accounts (owner, balance) VALUES ('Ганбаяр', 0);
SAVEPOINT sp_after_insert;
-- Оролдлого хийх
UPDATE accounts SET balance = balance + 50000 WHERE owner = 'Ганбаяр';
SAVEPOINT sp_after_update;
-- Буруу үйлдэл — зөвхөн энэ хэсгийг цуцал
UPDATE accounts SET balance = balance - 999999 WHERE owner = 'Ганбаяр';
-- sp_after_update цэг рүү буцах
ROLLBACK TO SAVEPOINT sp_after_update;
-- Ганбаяр 50000-тай хэвээр, бусад үйлдлүүд хэвээр
COMMIT;
SELECT owner, balance FROM accounts WHERE owner = 'Ганбаяр';
-- Ганбаяр: 50000
ACID баталгаа
PostgreSQL нь ACID гэсэн дөрвөн чанарыг бүрэн дэмждэг:
Atomicity (Бүтэн байдал) — Transaction дахь бүх үйлдэл бүгд амжилттай болох эсвэл бүгд цуцлагдана. Хагас дуусаагүй байдал байхгүй.
Consistency (Тогтвортой байдал) — Transaction дуусахад өгөгдлийн сан бүх хязгаарлалт (CHECK, FOREIGN KEY, UNIQUE) -г хангасан хэвээр байна.
Isolation (Тусгаарлалт) — Нэгэн зэрэг гүйцэтгэгдэж буй transaction-ууд бие биедээ нөлөөлөхгүй. Нэг transaction нөгөөгийн дуусаагүй өөрчлөлтийг харахгүй.
Durability (Тогтвортой хадгалалт) — COMMIT хийсний дараа тасалдал гарсан ч өгөгдөл алдагдахгүй, дискэнд бүрэн хадгалагдана.
-- Isolation жишээ: нэгэн зэрэг хоёр session ажиллаж байгаа мэт
-- Session 1
BEGIN;
UPDATE accounts SET balance = balance - 50000 WHERE owner = 'Болд';
-- Одоохондоо COMMIT хийгээгүй
-- Session 2 (нэгэн зэрэг)
SELECT balance FROM accounts WHERE owner = 'Болд';
-- Default isolation level дээр: COMMIT хийгдээгүй өөрчлөлт харагдахгүй
-- Үр дүн: 400000 (хуучин утга)
-- Session 1
COMMIT;
-- Одоо Session 2 шинэ утгыг харна: 350000
Дараагийн хичээлд:
Өгөгдлийн санд хэрэглэгч үүсгэж, тэдэнд хүснэгт, view, функцэд эрх олгох болон хасах аргыг сурна.