Transaction Isolation Level কী?

Isolation Level নির্ধারণ করে যে একটি Transaction অন্য Concurrent Transaction-এর পরিবর্তন থেকে কতটুকু বিচ্ছিন্ন থাকবে। Isolation Level বেশি হলে ডেটার সঠিকতা বাড়ে কিন্তু Performance কমে।


Isolation ছাড়া কী সমস্যা হয়?

১. Dirty Read

একটি Transaction অন্য Transaction-এর Commit হয়নি এমন ডেটা পড়তে পারে।

Transaction A: balance = 1000 থেকে 500 করলো (কিন্তু Commit হয়নি)
Transaction B: balance = 500 পড়লো
Transaction A: Rollback করলো → balance আবার 1000
Transaction B: ভুল ডেটা (500) নিয়ে কাজ করলো!

২. Non-Repeatable Read

একই Transaction-এ একই Row দুইবার পড়লে ভিন্ন ফলাফল পাওয়া যায়।

Transaction A: balance = 1000 পড়লো
Transaction B: balance = 500 করে Commit করলো
Transaction A: আবার balance = 500 পড়লো (আগের ফলাফলের সাথে মিলছে না!)

৩. Phantom Read

একই Transaction-এ একই Query দুইবার চালালে ভিন্ন সংখ্যক Row পাওয়া যায়।

Transaction A: salary > 50000 এমন 10 টি Row পড়লো
Transaction B: নতুন salary = 60000 এমন Row Insert করে Commit করলো
Transaction A: আবার salary > 50000 খুঁজলো → 11 টি Row পেলো!

চারটি Isolation Level

১. READ UNCOMMITTED (সবচেয়ে কম Isolation)

  • Dirty Read অনুমতি দেয়
  • সবচেয়ে দ্রুত, কিন্তু অনির্ভরযোগ্য
  • প্রায় কখনো ব্যবহার হয় না
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

২. READ COMMITTED (সাধারণ Default)

  • Dirty Read প্রতিরোধ করে
  • Non-Repeatable Read হতে পারে
  • PostgreSQL-এর Default Level
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

৩. REPEATABLE READ

  • Dirty Read + Non-Repeatable Read প্রতিরোধ করে
  • Phantom Read হতে পারে
  • MySQL InnoDB-এর Default Level
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

৪. SERIALIZABLE (সবচেয়ে বেশি Isolation)

  • সব ধরনের Read সমস্যা প্রতিরোধ করে
  • Transaction একের পর এক চলে (সবচেয়ে ধীর)
  • Financial system-এ ব্যবহার হয়
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Isolation Level তুলনা

Isolation Level Dirty Read Non-Repeatable Read Phantom Read
READ UNCOMMITTED ✅ হয় ✅ হয় ✅ হয়
READ COMMITTED ❌ নেই ✅ হয় ✅ হয়
REPEATABLE READ ❌ নেই ❌ নেই ✅ হয়
SERIALIZABLE ❌ নেই ❌ নেই ❌ নেই

Spring Boot-এ Isolation Level

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class AccountService {

    // READ_UNCOMMITTED: সবচেয়ে কম নিরাপদ (প্রায় ব্যবহার হয় না)
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public double getApproximateBalance(Long accountId) {
        return accountRepository.findById(accountId)
            .map(Account::getBalance).orElse(0.0);
    }

    // READ_COMMITTED: Dirty Read নেই (সাধারণ ব্যবহারের জন্য)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public List<Transaction> getRecentTransactions(Long accountId) {
        return transactionRepository.findByAccountId(accountId);
    }

    // REPEATABLE_READ: Balance consistent থাকবে (পুরো Transaction জুড়ে)
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void processMonthlyStatement(Long accountId) {
        Account account = accountRepository.findById(accountId).get();
        double openingBalance = account.getBalance();

        // কিছু হিসাব করা
        List<Transaction> txns = transactionRepository.findByAccountId(accountId);
        double closingBalance = calculateClosingBalance(openingBalance, txns);

        // এই পুরো সময়ে account.getBalance() একই থাকবে
        statementRepository.save(new Statement(accountId, openingBalance, closingBalance));
    }

    // SERIALIZABLE: সর্বোচ্চ নিরাপত্তা (Bank transfer-এর মতো critical কাজে)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void transferFunds(Long fromId, Long toId, double amount) {
        Account from = accountRepository.findById(fromId).get();
        Account to = accountRepository.findById(toId).get();

        from.setBalance(from.getBalance() - amount);
        to.setBalance(to.getBalance() + amount);

        accountRepository.save(from);
        accountRepository.save(to);
    }
}

application.properties-এ Default Isolation Level

# MySQL Default: REPEATABLE_READ
# PostgreSQL Default: READ_COMMITTED

# Spring Boot-এ ডিফল্ট ডেটাবেজের Isolation Level অনুসরণ করে
# প্রয়োজনে পরিবর্তন করুন
spring.datasource.hikari.transaction-isolation=TRANSACTION_READ_COMMITTED

কখন কোন Level ব্যবহার করবেন?

  • READ COMMITTED: সাধারণ Web Application, Report generation
  • REPEATABLE READ: Multi-step calculation, Batch processing
  • SERIALIZABLE: Financial transaction, Inventory booking
  • READ UNCOMMITTED: শুধু Approximate/Estimation কাজে

সংক্ষেপে

Level সমস্যা সমাধান Performance
READ UNCOMMITTED কিছুই না সর্বোচ্চ
READ COMMITTED Dirty Read ভালো
REPEATABLE READ Dirty + Non-Repeatable মাঝারি
SERIALIZABLE সব সমস্যা সবচেয়ে ধীর

উপসংহার

Transaction Isolation Level সঠিকভাবে বোঝা Production অ্যাপ্লিকেশনের জন্য অত্যন্ত গুরুত্বপূর্ণ। সঠিক Level নির্বাচন করুন — বেশি Isolation Performance কমায়, কম Isolation ডেটার সমস্যা তৈরি করে। বেশিরভাগ ক্ষেত্রে READ COMMITTED বা REPEATABLE READ যথেষ্ট। শুধুমাত্র Critical Financial বা Medical System-এ SERIALIZABLE ব্যবহার করুন।

Share