ডেটাবেজ Transaction কী?
Transaction হলো ডেটাবেজে একটি বা একাধিক SQL অপারেশনের একটি একক একক (unit) যা একসাথে সম্পন্ন হয়। হয় সবগুলো অপারেশন সফলভাবে সম্পন্ন হবে, না হলে কোনোটাই হবে না।
বাস্তব উদাহরণ: ব্যাংক Transfer — Account A থেকে টাকা কাটলে অবশ্যই Account B-তে টাকা যোগ হতে হবে। মাঝপথে কোনো সমস্যা হলে পুরো Transaction রদ হয়ে যাবে।
Transaction-এর ACID বৈশিষ্ট্য
| বৈশিষ্ট্য | বিবরণ |
|---|---|
| Atomicity | সব অপারেশন একসাথে সফল বা ব্যর্থ |
| Consistency | ডেটা সবসময় valid অবস্থায় থাকবে |
| Isolation | একাধিক Transaction পরস্পর থেকে বিচ্ছিন্ন |
| Durability | Commit হলে ডেটা স্থায়ীভাবে সংরক্ষিত |
SQL Transaction
-- Transaction শুরু
BEGIN TRANSACTION; -- বা START TRANSACTION;
-- Bank Transfer
UPDATE accounts SET balance = balance - 5000 WHERE id = 1; -- A থেকে কাটা
UPDATE accounts SET balance = balance + 5000 WHERE id = 2; -- B-তে যোগ
-- সফল হলে
COMMIT;
-- সমস্যা হলে
ROLLBACK;
Spring Boot-এ Transaction
@Transactional Annotation
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BankService {
@Autowired
private AccountRepository accountRepository;
// পুরো মেথড একটি Transaction-এ চলবে
@Transactional
public void transferMoney(Long fromId, Long toId, double amount) {
Account from = accountRepository.findById(fromId)
.orElseThrow(() -> new RuntimeException("Account not found"));
Account to = accountRepository.findById(toId)
.orElseThrow(() -> new RuntimeException("Account not found"));
if (from.getBalance() < amount) {
throw new RuntimeException("Insufficient balance!");
}
from.setBalance(from.getBalance() - amount);
to.setBalance(to.getBalance() + amount);
accountRepository.save(from);
accountRepository.save(to);
// Exception হলে স্বয়ংক্রিয়ভাবে ROLLBACK হবে
}
}
Transaction Propagation
Transaction Propagation নির্ধারণ করে — নতুন মেথড কলে নতুন Transaction তৈরি হবে নাকি বিদ্যমান Transaction-এ যোগ হবে।
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
// REQUIRED (ডিফল্ট): বিদ্যমান Transaction ব্যবহার করে, না থাকলে নতুন তৈরি করে
@Transactional(propagation = Propagation.REQUIRED)
public void placeOrder(Order order) {
orderRepository.save(order);
paymentService.processPayment(order); // একই Transaction-এ
inventoryService.reduceStock(order); // একই Transaction-এ
}
// REQUIRES_NEW: সবসময় নতুন Transaction তৈরি করে
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logAudit(String message) {
// এই Transaction আলাদা — Parent রোলব্যাক হলেও এটি সংরক্ষিত থাকে
auditRepository.save(new AuditLog(message));
}
// NESTED: Parent Transaction-এর ভেতরে Nested Transaction
@Transactional(propagation = Propagation.NESTED)
public void processPayment(Order order) {
// Savepoint তৈরি হয় — এই অংশ fail হলে শুধু এটুকু rollback হয়
paymentRepository.save(new Payment(order));
}
// NOT_SUPPORTED: Transaction ছাড়াই চলে
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public List<Product> getProductList() {
return productRepository.findAll();
}
}
Transaction Isolation Level
@Service
public class ReportService {
// READ_COMMITTED: Dirty Read প্রতিরোধ করে (সবচেয়ে সাধারণ)
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<Order> getOrders() {
return orderRepository.findAll();
}
// SERIALIZABLE: সর্বোচ্চ Isolation, Phantom Read প্রতিরোধ
@Transactional(isolation = Isolation.SERIALIZABLE)
public double calculateBalance(Long accountId) {
return accountRepository.findById(accountId)
.map(Account::getBalance)
.orElse(0.0);
}
}
Rollback নিয়ম
@Service
public class ProductService {
// ডিফল্ট: RuntimeException এবং Error-এ Rollback হয়
@Transactional
public void updateProduct(Product product) {
productRepository.save(product);
// RuntimeException হলে Rollback হবে
}
// Checked Exception-এও Rollback করতে চাইলে
@Transactional(rollbackFor = Exception.class)
public void importProducts(List<Product> products) throws IOException {
for (Product p : products) {
productRepository.save(p);
}
// IOException হলেও Rollback হবে
}
// নির্দিষ্ট Exception-এ Rollback করবে না
@Transactional(noRollbackFor = NotFoundException.class)
public void processOrders(List<Long> ids) {
for (Long id : ids) {
try {
processOrder(id);
} catch (NotFoundException e) {
// NotFoundException এ Rollback হবে না, অন্যগুলো চলতে থাকবে
log.warn("Order not found: " + id);
}
}
}
}
Read-Only Transaction
@Service
public class DashboardService {
// Read-Only Transaction — Performance উন্নত হয়
@Transactional(readOnly = true)
public DashboardData getDashboardData() {
long userCount = userRepository.count();
long orderCount = orderRepository.count();
double revenue = orderRepository.getTotalRevenue();
return new DashboardData(userCount, orderCount, revenue);
}
}
Transaction Timeout
@Service
public class ReportService {
// ৩০ সেকেন্ডের মধ্যে শেষ না হলে Transaction বাতিল
@Transactional(timeout = 30)
public byte[] generateLargeReport() {
// বড় রিপোর্ট তৈরির কাজ
return reportGenerator.generate();
}
}
সংক্ষেপে
| বিষয় | বিবরণ |
|---|---|
@Transactional |
মেথডকে Transaction-এ মোড়ে |
REQUIRED |
বিদ্যমান Transaction ব্যবহার করে (ডিফল্ট) |
REQUIRES_NEW |
সবসময় নতুন Transaction |
rollbackFor |
কোন Exception-এ Rollback হবে |
readOnly = true |
Read-only transaction (দ্রুত) |
timeout |
Transaction-এর সর্বোচ্চ সময় |
উপসংহার
Database Transaction ডেটার সামঞ্জস্য (Consistency) ও নির্ভরযোগ্যতা নিশ্চিত করে। Spring Boot-এ @Transactional Annotation ব্যবহার করে সহজেই Transaction Management করা যায়। Propagation, Isolation Level এবং Rollback নিয়ম সঠিকভাবে বুঝলে একটি robust ও নির্ভরযোগ্য অ্যাপ্লিকেশন তৈরি করা সম্ভব।