Transaction — ma’lumotlar bazasida bir nechta o‘qish va yozish amalini bitta mantiqiy birlik sifatida bajaradigan mexanizm. Transaction ichidagi amallar muvaffaqiyatli tugasa commit qilinadi, xato yuz bersa rollback orqali bekor qilinadi.
Transaction ma’lumot yaxlitligi, parallel requestlar va failure holatlarida database’ni kelishilgan holatda saqlash uchun ishlatiladi.
Boshlanish va yakun
Transaction odatda quyidagi lifecycle’ga ega:
BEGIN
→ SQL amallari
→ COMMIT yoki ROLLBACK
Misol:
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE id = 1;
UPDATE accounts
SET balance = balance + 100
WHERE id = 2;
COMMIT;
Ikkinchi amal xato bersa birinchi update ham saqlanmasligi kerak.
Commit
Commit transactiondagi barcha o‘zgarishlarni yakuniy tasdiqlaydi.
Commitdan keyin:
- o‘zgarish durable bo‘lishi;
- boshqa transactionlarga ko‘rinishi;
- locklar bo‘shatilishi;
- transaction logga tegishli yozuv tushishi
mumkin.
Commit javobi kelmasdan connection uzilsa natija noaniq qolishi mumkin.
Rollback
Rollback transactiondagi commit qilinmagan o‘zgarishlarni bekor qiladi.
Rollback quyidagi holatlarda ishlatiladi:
- validation xatosi;
- constraint buzilishi;
- deadlock;
- application exception;
- manual bekor qilish;
- timeout.
Database tashqi HTTP request yoki email kabi side effectlarni rollback qilmaydi.
Atomicity
Transaction barcha database amallarini “hammasi yoki hech narsa” modeli bilan bajaradi.
Bu ayniqsa:
uchun muhim.
Atomicity bir nechta mustaqil service’ni avtomatik qamrab olmaydi.
Isolation
Parallel transactionlar bir-birining oraliq holatini qanchalik ko‘rishini isolation level belgilaydi.
Keng tarqalgan darajalar:
- Read Uncommitted;
- Read Committed;
- Repeatable Read;
- Serializable.
Aniq anomaly va xatti-harakat database implementationiga qarab farq qilishi mumkin.
Read Committed
Har statement faqat commit qilingan ma’lumotni ko‘radi.
Bir transaction ichida ayni row ikki marta o‘qilganda boshqa transaction commit qilgan yangi qiymat ko‘rinishi mumkin.
Bu ko‘p database’larda keng tarqalgan default daraja.
Repeatable Read
Transaction davomida o‘qilgan ma’lumotning barqarorroq snapshoti saqlanadi.
Ayni row qayta o‘qilganda bir xil qiymat ko‘rinadi.
Phantom yoki write skew kabi holatlar implementationga bog‘liq.
Serializable
Transactionlar biror ketma-ket tartibda bajarilgandek natija beradi.
Bu eng kuchli isolationga yaqin.
- lock;
- predicate lock;
- serialization conflict;
- optimistic abort
orqali buni ta’minlashi mumkin.
Conflict yuz bersa application transactionni retry qiladi.
Autocommit
Ko‘p database clientlarda har SQL statement alohida transaction sifatida avtomatik commit qilinadi.
Masalan:
UPDATE users SET active = true WHERE id = 15;
alohida transaction bo‘lishi mumkin.
Bir nechta statement atomik bo‘lishi kerak bo‘lsa explicit transaction ochiladi.
Savepoint
Transaction ichida oraliq nuqta yaratiladi.
SAVEPOINT before_items;
Xato yuz bersa:
ROLLBACK TO SAVEPOINT before_items;
orqali butun transaction emas, ma’lum qism bekor qilinadi.
Savepoint tashqi side effectlarni qaytarmaydi.
Nested transaction
Application framework nested transaction API berishi mumkin.
Ko‘p implementationda ichki transaction haqiqiy mustaqil commit emas, savepointga o‘xshash ishlaydi.
Tashqi transaction rollback qilinsa ichki “commit” natijasi ham yo‘qoladi.
Framework semantikasi aniq tekshiriladi.
Lock
Transaction o‘qigan yoki o‘zgartirgan resource’lar lock bilan himoyalanishi mumkin.
Lock turlari:
Lock qancha uzoq saqlansa parallel requestlar shuncha ko‘p kutadi.
MVCC
Multi-Version Concurrency Control reader va writerlar bir-birini kamroq bloklashi uchun row versiyalaridan foydalanadi.
Reader transaction snapshotga mos eski versiyani ko‘rishi mumkin.
Eski versiyalar keyinchalik vacuum yoki garbage collection bilan tozalanadi.
Deadlock
Ikki transaction bir-biriga kerak bo‘lgan lockni ushlab tursa deadlock yuz beradi.
Database cycle’ni aniqlab, transactionlardan birini abort qiladi.
Application deadlock xatosini transient holat sifatida retry qilishi mumkin.
Locklarni bir xil tartibda olish deadlock ehtimolini kamaytiradi.
Transaction hajmi
Juda katta transaction:
xarajatini oshiradi.
Katta importlar boshqariladigan batchlarga ajratiladi.
Biroq batchlar orasidagi atomicity talabi alohida ko‘rib chiqiladi.
Uzoq transaction
User input yoki tashqi API javobini kutib turib transactionni ochiq qoldirish yomon amaliyot.
Bu:
- locklarni uzoq saqlaydi;
- connection poolni band qiladi;
- eski snapshotni ushlab turadi;
- deadlock ehtimolini oshiradi.
Kerakli data tayyorlangach qisqa transaction ochiladi.
Retry
Serialization failure, deadlock yoki vaqtinchalik connection muammosida transaction qayta bajarilishi mumkin.
Retry block ichida:
- email yuborish;
- tashqi payment;
- random non-deterministik side effect
takrorlanmasligi kerak.
Outbox va idempotency yordamida tashqi amallar transactiondan ajratiladi.
Connection uzilishi
Client commit yuborgach connection uzilsa server commit qilgan yoki qilmaganini bilish qiyin.
Client operationni ko‘r-ko‘rona takrorlamaydi.
Unique business key, transaction ID yoki status endpoint orqali natija aniqlanadi.
Read-only transaction
Faqat o‘qish uchun transaction explicit read-only deb belgilanishi mumkin.
Database bunday transactionga optimizatsiya qo‘llashi yoki write’ni rad etishi mumkin.
Report va consistent snapshot uchun foydali.
Transaction boundary
Transaction application service yoki requestning aniq business chegarasiga mos bo‘ladi.
Juda mayda boundary invariantni buzishi, juda katta boundary esa lock va retry xarajatini oshirishi mumkin.
Bir transaction ichida faqat birgalikda commit bo‘lishi zarur amallar saqlanadi.
Bog‘liq tushunchalar
Commit, Rollback, Atomicity, Isolation, Durability, Savepoint, MVCC, Locking, Deadlock, Serializable, ACID